Learning Check

When you complete this session, you will be able to:

  1. understand the assumptions in SLR;
  2. understand how to critically assessing a regression model;
  3. perform regression diagnostics checking for Simple Linear Regression;
  4. understand outliers and leverage;
  5. perform some simple transformations.

Before you start, load the stored datasets provided for exercises below by running the following chunk (assuming the file “InsulatingData.Rdata” is saved in the same directory as the .Rmd worksheet).

Question 1 The timing of production runs (Sheather, 2009)

The original data are in the form of the time taken (in minutes) for a production run, \(Y\), and the number of items produced, \(X\), for 20 randomly selected orders as supervised by three managers. At this stage we shall only consider the data for one of the managers.

(a). Open the Excel file production.txt. Construct a scatterplot of production run, \(Y\), and the number of items produced, \(X\). Fit the least squares line to the data using R. Explain the fitted model, by interpreting the slope and intercept.

production=read.table("production.txt", header=T)
production
prod.lm=lm(RunTime ~ RunSize, data=production) ## the LS line
prod.lm1=lm(RunTime ~ 10*RunSize, data=production)
Error in terms.formula(formula, data = data) : 
  invalid model formula in ExtractVars

The equation of the least squares line of best fit is

\[y = 149.7 + 0.26x.\]

The intercept is 149.7, which is where the line of best fit crosses the run time axis. The intercept in the model has the following interpretation: for any production run, the average set up time is 149.7 minutes.

The slope of the line is 0.26. Thus, we say that each additional unit to be produced is predicted to add 0.26 minutes to the run time.

The value of \(R^2= 0.7302\) which implies that 73.02% of the information (variation) in Run Time is explained by the least squares regression line, suggesting that the model is a good model.

(b). Construct residual diagnostic plots, and assess whether you think that the assumptions for linear regression have been satisfied. You can use the function rstudent (or rstandard) to first standardize the residuals.

First, we manually check the normality through histograms and QQ-plots of residuals and standardised residuals.

names(prod.lm)  ## checking the output of the fitted model, residuals
 [1] "coefficients"  "residuals"     "effects"       "rank"          "fitted.values" "assign"        "qr"           
 [8] "df.residual"   "xlevels"       "call"          "terms"         "model"        
res=prod.lm$residuals
std.res=rstandard(prod.lm)  ## standardised residuals
par(mfrow=c(2,2))  ## plotting 4 plots to check normality
hist(res)
hist(std.res)
qqnorm(res)
qqline(res)
qqnorm(std.res)
qqline(std.res)
par(mfrow=c(1,1))

From the above histograms and QQ-plots, the normality is satisfied.

par(mfrow=c(2,2))
plot(res, xlab="Time", ylab="Residuals") ## Residuals vs Time
plot(std.res,xlab="Time", ylab="Standardised Residuals")
plot(production$RunSize,res, xlab="Run Size", ylab="Residuals") # Residuals vs x
plot(production$RunSize,std.res,  xlab="Run Size", ylab="Standardised Residuals")

 - The next residual analysis is to check about randomness (independence) and constant variance. We plot both
 residuals and standardised residuals against time (top left and top right). From these plots we can confirm the
 the residual are random scattered with no pattern whatsoever.

 - The bottom left plot shows the residuals against Run Size to check randomness (no pattern) and constant
 variance. The bottom right plot provides the standardised residuals against fitted values to check randomness (no
 pattern) and constant variance. Both plots confirm randomness and constant variance.

(c). Using the fitted model.

par(mfrow=c(2,2)) # to view 2x2 plots
plot(prod.lm)

plot(prod.lm1)

The figure above provides diagnostic plots produced by R when the command plot(prod.lm) is used, where prod.lm is the result of the “lm” command.

+ The top left plot shows the residuals against fitted values to check randomness (no pattern) and linearity. 

+ The bottom left provides the standardised residuals against fitted values to check randomness (no pattern) and constant variance. The smoothing curve using standardised residuals is almost flat (i.e constant) to confirm randomness and constant variance.

+ The top right plot is a normal Q–Q plot. Most of the observations lie around the straight line, confirming Normality.

+ The bottom right plot of standardized residuals against leverage enables one
to readily identify any ‘bad’ leverage points. 

   - Recall that the rule for simple linear regression for classifying a point as a leverage
   point is if leverage $h_{ii} > 4/ n.$ As $n=20$, the rule is $h_{ii} > 0.2.$ As leverage $h_{ii}$ in the above
   bottom right is less than 0.2, then there is no leverage points.

   - Recall that we classify points as outliers if their standardized residuals have absolute value greater than
   2. All the residuals are within (-2,2), therefore no outliers being detected.

Question 2 The invoices data (Sheather, 2009)

The manager of the purchasing department of a large company would like to develop a regression model to predict the average amount of time it takes to process a given number of invoices. Over a 30-day period, data are collected on the number of invoices processed and the total time taken (in hours). The data are available in the file invoices.txt.

Complete the following tasks.

(a). Fit the least squares line to the data using R. Explain the fitted model, by interpreting the slope and intercept.

invoices=read.table("invoices.txt", header=T)
View(invoices)
inv.lm=lm(Time ~ Invoices, data=invoices)
plot(Time ~ Invoices, data=invoices)
abline(inv.lm)

summary(inv.lm)

Call:
lm(formula = Time ~ Invoices, data = invoices)

Residuals:
     Min       1Q   Median       3Q      Max 
-0.59516 -0.27851  0.03485  0.19346  0.53083 

Coefficients:
             Estimate Std. Error t value Pr(>|t|)    
(Intercept) 0.6417099  0.1222707   5.248 1.41e-05 ***
Invoices    0.0112916  0.0008184  13.797 5.17e-14 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.3298 on 28 degrees of freedom
Multiple R-squared:  0.8718,    Adjusted R-squared:  0.8672 
F-statistic: 190.4 on 1 and 28 DF,  p-value: 5.175e-14

The equation of the least squares line of best fit is

\[ Time= 0.642 + 0.011 Invoices .\]

The intercept is 0.642, which is not interpretable for no invoices.

The slope of the line is 0.011. Thus, we say for that for each additional invoice, the average amount of time it takes to process increases by 0.011 hour.

(b). Construct residual diagnostic plots, and assess whether you think that the assumptions for linear regression have been satisfied. You can use the function rstudent (or rstandard) to first standardize the residuals.

First, we check the normality through histograms and QQ-plots of residuals and standardised residuals.

names(inv.lm)  ## checking the output of the fitted model, residuals
 [1] "coefficients"  "residuals"     "effects"       "rank"          "fitted.values"
 [6] "assign"        "qr"            "df.residual"   "xlevels"       "call"         
[11] "terms"         "model"        
res=inv.lm$residuals
std.res=rstandard(inv.lm)  ## standardised residuals
par(mfrow=c(2,2))  ## plotting 4 plots to checkk normality
hist(res)
hist(std.res)
qqnorm(res)
qqline(res)
qqnorm(std.res)
qqline(std.res)
par(mfrow=c(1,1))

The histograms show bimodalities. From the QQ-plots, the normality seems to be satisfied, except 1 point at the top and 1 point at the bottom respectively.

par(mfrow=c(2,2))
plot(res, xlab="Time", ylab="Residuals")
plot(std.res,xlab="Time", ylab="Standardised Residuals")
plot(res, invoices$Invoices, xlab="Invoices", ylab="Residuals")
plot(std.res, invoices$Invoices,  xlab="Invoices", ylab="Standardised Residuals")

The next residual analysis is to check about randomness (independence) and constant variance. We plot both residuals and standardised residuals against time (top left and top right). From these plots we can see a bit of increasing pattern, small residuals within 0-15 and then larger residuals within 15-30.

The bottom left plot shows the residuals against Invoices to check randomness (no pattern) and constant variance. The bottom right plot provides the standardised residuals against fitted values to check randomness (no pattern) and constant variance. Both plots show a bit of pattern between negative and positive Invoices.

(c). Perform diagnostic checking for the fitted model in (a) using “plot(file.lm).” Interpret the outputs.

par(mfrow=c(2,2))
plot(inv.lm)

(d). Use the function influence.measures to explore measures of leverage and Cook’s distance.

# check help function first
Inv.infl<-influence.measures(inv.lm)
Inv.infl
Influence measures of
     lm(formula = Time ~ Invoices, data = invoices) :
#head(Inv.infl$infmat)

Points increase in influence to the extent that they lie on their own, a long way from the mean of \(x\) and the bulk of the data. The column “hat” in the above is the commonest measure of this leverage and is defined by:

\[h_i = \frac{1}{n} + \frac{(x_i-\bar{x})^2}{\sum(x_j -\bar{x})^2} .\]

Cook’s distance (the column “cook.d” in the above) is one measure of influence: for each point, it combines the size of its residual along with a measure of the leverage. An approximate cutoff is \(4/(n-2)\), but in practice it is important to look for gaps in values of Cook’s distance instead of just whether or not the values exceed the cutoff.

There are 2 functions which can also be used to calculate these measures directly: hatvalues and cooks.distance.

Leverage.inv<-hatvalues(inv.lm)
Cooks.Dist.inv<-cooks.distance(inv.lm)
Inv <- invoices$Invoices
# plotting the influence measures against their x value - Invoices 
n=30
plot(Leverage.inv~Inv)
abline(h=4/n, col=3)
plot(Cooks.Dist.inv~Inv)
abline(h=4/(n-2), col=2)
# plotting the influence measures against their x value - Invoices 
n=30
plot(Leverage.inv~Inv)
abline(h=4/n, col=3)

plot(Cooks.Dist.inv~Inv)
abline(h=4/(n-2), col=2)

sort(Leverage.inv)
        28         26          1         11         24         25         16         15 
0.03348526 0.03395333 0.03554890 0.03580511 0.03783426 0.04002682 0.04268500 0.04470347 
        12         29          9          7          3         17         22         21 
0.04695762 0.04875109 0.04933167 0.05065542 0.05402803 0.05548070 0.05552997 0.05775210 
         2         13          5         27          6         20          8         10 
0.06354063 0.06354063 0.06435114 0.06435114 0.06529058 0.07786621 0.08542440 0.09496328 
        30         18         14          4         23         19 
0.09620163 0.09863069 0.10127820 0.10389038 0.10917143 0.18897091 

Question 3 (From Weisberg, S. (2005). Applied Linear Regression, 3rd edition. New York: Wiley)

In this question, you will be learning the R code in more detail to provide better visualisation which may be needed for your project. Furthermore, the ANOVA is explained in more detail following the lecture (part c).

The R data file Wind.RData contains a data frame (wm1) containing wind speed data (in m/s) at two sites: a reference site (Rspd) and a candidate site (CSpd). Data were collected every 6 hours for the year 2002 except in the month of May. The objective is to be able to determine whether wind speed at the reference site, which has permanent wind speed monitoring equipment, can be used to predict the wind speed at this candidate site in the future in order to determine whether to place a small wind farm there.

sort(Cooks.Dist.inv)
          10           16           20            8            9           14 
0.0002035386 0.0005353096 0.0010595498 0.0011024438 0.0032903108 0.0033298164 
          17           28           29            4            1           18 
0.0036431399 0.0045459002 0.0059479355 0.0061181410 0.0088295724 0.0090501347 
           7            5           24           25           11            6 
0.0092145747 0.0150936105 0.0174505677 0.0201627039 0.0260821401 0.0302309933 
          21           12           22           26           19           27 
0.0308161815 0.0341277200 0.0387338505 0.0423707984 0.0502287555 0.0510541088 
           3            2           15           13           23           30 
0.0599026174 0.0770062759 0.0797769665 0.0898041145 0.1207897984 0.1525784387 
  1. Draw a scatterplot of the response CSpd against the predictor RSpd and label it appropriately.
par(pty = "s") # A graphical parameter that sets the PlotTYpe to "square"

# The syntax of the plot statement says "plot CSpd against RSpd but extract them 
# from the data frame wm1. The xlim and ylim arguments are the same - the range 
# of all the data. 
plot(CSpd ~ RSpd, data = wm1, 
     xlab = "Wind speed at reference site (m/s)", 
     ylab = "Wind speed at candidate site (m/s)",
     main = "Wind speeds at reference and candidate sites",
     xlim = range(c(wm1$CSpd, wm1$RSpd)), ylim = c(range(c(wm1$CSpd, wm1$RSpd)))) 


nrow(wm1)
[1] 1116

Fit a simple linear model to these data, and present the appropriate regression summaries. Plot the fitted line onto the plot in (a).

# Load the workshop data here
load("Wind.RData")
nrow('Wind.RData')
NULL

To plot the fitted line onto an existing plot in R or RStudio, you only need to invoke the abline command (from the console) that we’ve used already and that’s shown below. Here, however, because I want to produce a separate plot from the one above, I have to re-plot the data using the above commands and then invoke abline.

# Notice the similarity with the plot statement above
Wind.lm <- lm(CSpd ~ RSpd, data = wm1)
# Here are the contents of the object Wind.lm:
names(Wind.lm)
 [1] "coefficients"  "residuals"     "effects"       "rank"          "fitted.values"
 [6] "assign"        "qr"            "df.residual"   "xlevels"       "call"         
[11] "terms"         "model"        
# and here's some basic output:
Wind.lm

Call:
lm(formula = CSpd ~ RSpd, data = wm1)

Coefficients:
(Intercept)         RSpd  
     3.1412       0.7557  
# A bit more comes from the summary() function:
summary(Wind.lm)

Call:
lm(formula = CSpd ~ RSpd, data = wm1)

Residuals:
    Min      1Q  Median      3Q     Max 
-7.7877 -1.5864 -0.1994  1.4403  9.1738 

Coefficients:
            Estimate Std. Error t value Pr(>|t|)    
(Intercept)  3.14123    0.16958   18.52   <2e-16 ***
RSpd         0.75573    0.01963   38.50   <2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 2.466 on 1114 degrees of freedom
Multiple R-squared:  0.5709,    Adjusted R-squared:  0.5705 
F-statistic:  1482 on 1 and 1114 DF,  p-value: < 2.2e-16
  1. Construct the four diagnostic plots that we discussed in the lecture. Do you think the simple linear model is a good fit? What improvements might you suggest?
par(pty = "s")
plot(CSpd ~ RSpd, data = wm1, 
     xlab = "Wind speed at reference site (m/s)", 
     ylab = "Wind speed at candidate site (m/s)",
     main = "Wind speeds at reference and candidate sites",
     xlim = range(c(CSpd, RSpd)), ylim = c(range(c(CSpd, RSpd)))) 
# abline() takes two arguments: a slope and an intercept. We can
# extract these from the object Wind.lm (which is a list) by 
# using the $ operator, e.g., Wind.lm$coefficients (try it!) and
# using that as an argument to abline():
abline(Wind.lm$coef) # or simply abline(Wind.lm)

The interpretation:

     - Plot 1 - Residuals vs Fitted: There is no clear pattern, eventhough large fitted values seem to have smaller residuals.

     - Plot 2 - Scale - Location: There is no clear pattern, eventhough large fitted values seem to have smaller residuals.

     - Plot 3 - QQ plot of standardised residuals: while most of the points are on the straight line, some points on the upper part are off the lines. Normality might not be satisfied.

     - Plot 4 - Residuals vs Leverage: As $n=1116$ then the cut-off for Cook's distance is $D_i > 4/(n-2)=0.0036.$ We can see that many of the standardised residuals with the leverage greater than 0.04. 
     

Question 4: House selling price data

A set of data on the selling price \(Y\) (in $10,000) and annual taxes \(X\) (in $1,000) for 24 houses is available available online, {housesellingprice.txt}.

  1. Assuming that a simple linear regression model is appropriate, obtain the least squares fit relating selling price to taxes paid. What is the estimate of \(\sigma^2\)?

Read data in

par(mfrow=c(2,2))  # Places 4 graphs together on the same plotting region
plot(Wind.lm)

Simple Linear regression fit

house = read.table("housesellingprice.txt",header=T)
summary(house)
     sales           taxes      
 Min.   :25.90   Min.   :3.891  
 1st Qu.:29.90   1st Qu.:5.057  
 Median :33.70   Median :5.974  
 Mean   :34.61   Mean   :6.405  
 3rd Qu.:38.15   3rd Qu.:7.873  
 Max.   :45.80   Max.   :9.142  

\(\widehat\beta_0=13.3202\), \(\widehat\beta_1=3.3244\)

house.lm<-lm(sales~taxes,data=house)
summary(house.lm)

Call:
lm(formula = sales ~ taxes, data = house)

Residuals:
    Min      1Q  Median      3Q     Max 
-3.8343 -2.3157 -0.3669  1.9787  6.3168 

Coefficients:
            Estimate Std. Error t value Pr(>|t|)    
(Intercept)  13.3202     2.5717   5.179 3.42e-05 ***
taxes         3.3244     0.3903   8.518 2.05e-08 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 2.961 on 22 degrees of freedom
Multiple R-squared:  0.7673,    Adjusted R-squared:  0.7568 
F-statistic: 72.56 on 1 and 22 DF,  p-value: 2.051e-08

\(\widehat\sigma^2={Residual MS}=8.77\)

  1. Find the mean selling price given that the taxes paid are \(7.50\).
anova(house.lm)
Analysis of Variance Table

Response: sales
          Df Sum Sq Mean Sq F value    Pr(>F)    
taxes      1 636.16  636.16  72.556 2.051e-08 ***
Residuals 22 192.89    8.77                      
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

the mean selling price \(=38.25296\) that the taxes paid are \(X_0=7.50\).

  1. Construct a graph of \(Y\) versus \(X\). Then add the fitted line, the 95% confidence interval of the mean response, and the 95% prediction interval of the new actual values on the graph.
predict(house.lm,newdata=data.frame(taxes=7.5),interval="confidence",level=0.95)
       fit      lwr      upr
1 38.25296 36.71776 39.78816
  1. Perform diagnostic checking for the fitted model in (a) using “plot(file.lm).” Interpret the outputs.
with(house,plot(sales~taxes,type="p"))
with(house,lines(fitted(house.lm)~taxes))
new = data.frame(taxes=seq(3,10,.1))
CIs = predict(house.lm,new,interval="confidence")
PIs = predict(house.lm,new,interval="predict")
matpoints(new$taxes,CIs,lty=c(1,2,2),col=c("black","red","red"),type="l")
matpoints(new$taxes,PIs,lty=c(1,2,2),col=c("black","blue","blue"),type="l")

par(mfrow=c(2,2))
plot(house.lm)

# check help function first
house.lev<-hatvalues(house.lm)
house.lev
         1          2          3          4          5          6          7          8 
0.08009597 0.07494802 0.10189804 0.10097003 0.07310359 0.15145530 0.04613071 0.05281317 
         9         10         11         12         13         14         15         16 
0.04744471 0.06286388 0.04197728 0.04511789 0.07355860 0.10057696 0.04314772 0.07471120 
        17         18         19         20         21         22         23         24 
0.16214717 0.04466605 0.06413614 0.14091382 0.04346584 0.10811699 0.09396602 0.17177488 
    - Recall that the rule for simple linear regression for classifying a point as a leverage
    point is if leverage $h_{ii} > 4/ n.$ As $n=24$, the rule is $h_{ii} > 0.167.$ As leverage $h_{ii}$ in the  
    above output shows that one point (observation no 24) with $h_{ii}=0.17177 > 0.167$ , then there is one
    leverage point.

    - Recall that we classify points as outliers if their standardized residuals have
    absolute value greater than 2. There is one observation (no 15) with the standard residual is greater than  
    2. However observation number 24, the leverage point,  with standard residual less than 2 is a good
    leverage point.
    
    

Question 5 Bid data (Sheather, 2009)

A building maintenance company is planning to submit a bid on a contract to clean corporate offices scattered throughout an office complex. The costs incurred by the maintenance company are proportional to the number of cleaning crews needed for this task. Recent data are available for the number of rooms that were cleaned by varying numbers of crews. For a sample of 53 days, records were kept of the number of crews used and the number of rooms that were cleaned by those crews. The data can be found in the file cleaning.txt.

The aim is to develop a regression equation to model the relationship between the number of rooms cleaned and the number of crews.

Complete the following tasks.

(a). Fit the least squares line to the data using R. Explain the fitted model, by interpreting the slope and intercept.

std.res.h=rstandard(house.lm)
#std.res.h
sort(std.res.h)
         14           1          23          11           8           4          22 
-1.36539093 -1.32680727 -1.23490307 -1.09307472 -1.05824009 -0.91550077 -0.79182376 
         12           7           3           2          19           5          13 
-0.77096776 -0.70102563 -0.18618750 -0.17949347 -0.17219414 -0.08436379 -0.03798314 
         10          17          16          20          24           9           6 
 0.19524305  0.19658735  0.45732239  0.70746820  0.77548911  1.10892170  1.33622425 
         18          21          15 
 1.47498387  1.50462011  2.18088723 
bid=read.table("cleaning.txt", header=T)
head(bid)

The equation of the least squares line of best fit is

\[Rooms = 1.78 + 3.70 Crews.\]

The intercept is \(1.78 \approx 2\) which is where the line of best fit crosses the Rooms axis. The intercept in the model has the following interpretation: for Crews=0, the average of number of cleaned room is 2.

The slope of the line is \(3.70 \approx 4\). Thus, we say that for each additional crew, it is predicted to add 4 rooms are being cleaned.

(b). Construct residual diagnostic plots, and assess whether you think that the assumptions for linear regression have been satisfied. You can use the function rstudent (or rstandard) to first standardize the residuals.

First, we manually check the normality through histograms and QQ-plots of residuals and standardised residuals.

bid.lm=lm(Rooms ~ Crews, data=bid) ## the LS line
plot(Rooms ~ Crews, data=bid, xlab="Number of Crews", ylab="Number of Rooms")
abline(bid.lm)

summary(bid.lm)

Call:
lm(formula = Rooms ~ Crews, data = bid)

Residuals:
     Min       1Q   Median       3Q      Max 
-15.9990  -4.9901   0.8046   4.0010  17.0010 

Coefficients:
            Estimate Std. Error t value Pr(>|t|)    
(Intercept)   1.7847     2.0965   0.851    0.399    
Crews         3.7009     0.2118  17.472   <2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 7.336 on 51 degrees of freedom
Multiple R-squared:  0.8569,    Adjusted R-squared:  0.854 
F-statistic: 305.3 on 1 and 51 DF,  p-value: < 2.2e-16

From the above histograms and QQ-plots, the normality is satisfied.

res.bid=bid.lm$residuals
std.res.bid=rstandard(bid.lm)  ## standardised residuals
par(mfrow=c(2,2))  ## plotting 4 plots to check normality
hist(res.bid)
hist(std.res.bid)
qqnorm(res.bid)
qqline(res.bid)
qqnorm(std.res.bid)
qqline(std.res.bid)
par(mfrow=c(1,1))

 - The next residual analysis is to check about randomness (independence) and constant variance. We plot both
 residuals and standardised residuals against time (top left and top right). From these plots we can confirm the
 the residual are random scattered with no pattern whatsoever. However, there seems to show an increasing trend for variances.

 - The bottom left plot shows the residuals against Number of Crews to check randomness (no pattern) and constant variance. The bottom right plot provides the standardised residuals against fitted values to check randomness (no pattern) and constant variance. 

- It is clear that  the variability in the standardized residuals tends to increase  with the number of crews. Thus, the assumption that the variance of the errors is constant appears to be violated in this case. 

(c). Perform diagnostic checking for the fitted model in (a) using “plot(file.lm).” Interpret the outputs.

par(mfrow=c(2,2))
plot(res.bid, xlab="Time", ylab="Residuals") ## Residuals vs Time
plot(std.res.bid,xlab="Time", ylab="Standardised Residuals")
plot(bid$Crews,res.bid, xlab="Number of Crews", ylab="Residuals") # Residuals vs x
plot(bid$Crews,std.res.bid,  xlab="Number of Crews", ylab="Standardised Residuals")

   -  The top left plot shows the residuals against fitted values to check randomness (no pattern) and linearity.  The smoothing curve shows a reasonable linear relationship and no pattern.

   - The bottom left provides the squared root of standardised residuals against fitted values to check randomness (no pattern) and constant variance. The smoothing curve using standardised residuals is an increasing trend which means that constant variance may not be satisfied.

    - The top right plot is a normal Q–Q plot. Most of the observations lie around the straight line except the two points, confirming Normality.

    -  The bottom right plot of standardized residuals against leverage enables one to readily identify any ‘bad’ leverage points (ie large leverage and large standardised residuals) 

(d). As the data on each axis are in the form of counts and are measured in the same units, the square root transformation of both the predictor variable and the response variable should be implemented. Apply these transformations and repeat (a).

par(mfrow=c(2,2))
plot(bid.lm)

(e). Perform diagnostic checking for the fitted model in (d) using “plot(file.lm).” Interpret the outputs.

bid.sq.lm=lm(sqrt(Rooms) ~ sqrt(Crews), data=bid) ## the LS line
plot(sqrt(Rooms) ~ sqrt(Crews), data=bid, xlab="Square Root of Number of Crews", ylab="Square Root of Number of Rooms")
abline(bid.sq.lm)

summary(bid.sq.lm)

Call:
lm(formula = sqrt(Rooms) ~ sqrt(Crews), data = bid)

Residuals:
     Min       1Q   Median       3Q      Max 
-1.09825 -0.43988  0.06826  0.42726  1.20275 

Coefficients:
            Estimate Std. Error t value Pr(>|t|)    
(Intercept)   0.2001     0.2757   0.726    0.471    
sqrt(Crews)   1.9016     0.0936  20.316   <2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.594 on 51 degrees of freedom
Multiple R-squared:   0.89, Adjusted R-squared:  0.8879 
F-statistic: 412.7 on 1 and 51 DF,  p-value: < 2.2e-16
     - After the transformation, the bottom left-hand plot further demonstrates the 
     benefit of the square root transformation in terms of stabilizing the error term.  
     
     - Thus, taking the square root of both the  x  and the  y  variables has stabilized
     the variance of the random errors and hence produced a valid model.  

(f). Predict the number of rooms that can be cleaned by 4 crews and by 16 crews and its 95% confidence intervals using the models in (a) and (d) respectively.

Using (a)

par(mfrow=c(2,2))
plot(bid.sq.lm)

Using (d)

conf.pred0=predict(bid.lm,newdata=data.frame(Crews=c(4,16)),interval="prediction",level=0.95)
conf.pred0
       fit      lwr      upr
1 16.58827  1.58941 31.58713
2 60.99899 45.81025 76.18773
   - We can see that the prediction interval based on the transformed data is narrower 
   than that  based on the untransformed data when the number of crews is 4 (7.78, 
   27.21) vs (1.58, 31.59) and wider when the number of crews is 16 [(43.33, 81.55) is 
   wider than (45.81, 76.19)]. 

   - This is expected as the original scale the data have variance which increases as 
   the  x -variable increases which means that realistic prediction intervals will
   get wider as the  x -variable increases.  

  - In summary, ignoring nonconstant variance in the raw data from this example led to 
  invalid prediction intervals. 
  
  
LS0tCnRpdGxlOiAiU1RBVDI0MDEgQW5hbHlzaXMgb2YgRXhwZXJpbWVudHMiCmF1dGhvcjogJyoqUHJhY3RpY2FsIFdlZWsgNjogU29sdXRpb25zKionCiNkYXRlOiAiUHJhY3RpY2FsIDIiCm91dHB1dDoKICBodG1sX2RvY3VtZW50OgogICAgaGlnaGxpZ2h0OiBoYWRkb2NrCiAgICAjIG51bWJlcl9zZWN0aW9uczogeWVzCiAgICB0aGVtZTogZmxhdGx5CiAgICB0b2M6IHllcwogIGh0bWxfbm90ZWJvb2s6CiAgICBoaWdobGlnaHQ6IGhhZGRvY2sKICAgICMgbnVtYmVyX3NlY3Rpb25zOiB5ZXMKICAgIHRoZW1lOiBmbGF0bHkKICBwZGZfZG9jdW1lbnQ6CiAgICB0b2M6IHllcwogIHdvcmRfZG9jdW1lbnQ6CiAgICBoaWdobGlnaHQ6IHRhbmdvCiAgICB0b2M6IHllcwotLS0KCgpgYGB7ciBlY2hvPUZBTFNFfQprbml0cjo6b3B0c19jaHVuayRzZXQocHJvbXB0PUZBTFNFLCBjb21tZW50PU5BLCB0aWR5PVRSVUUsIGVycm9yPVRSVUUsIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0UpCmBgYAoKCiMjIExlYXJuaW5nIENoZWNrCgpXaGVuIHlvdSBjb21wbGV0ZSB0aGlzIHNlc3Npb24sIHlvdSB3aWxsIGJlIGFibGUgdG86CgoxLiB1bmRlcnN0YW5kIHRoZSBhc3N1bXB0aW9ucyBpbiBTTFI7CjIuIHVuZGVyc3RhbmQgaG93IHRvIGNyaXRpY2FsbHkgYXNzZXNzaW5nIGEgcmVncmVzc2lvbiBtb2RlbDsKMy4gcGVyZm9ybSByZWdyZXNzaW9uIGRpYWdub3N0aWNzIGNoZWNraW5nIGZvciBTaW1wbGUgTGluZWFyIFJlZ3Jlc3Npb247CjQuIHVuZGVyc3RhbmQgb3V0bGllcnMgYW5kIGxldmVyYWdlOwo1LiBwZXJmb3JtIHNvbWUgc2ltcGxlIHRyYW5zZm9ybWF0aW9ucy4KCgpCZWZvcmUgeW91IHN0YXJ0LCBsb2FkIHRoZSBzdG9yZWQgZGF0YXNldHMgcHJvdmlkZWQgZm9yIGV4ZXJjaXNlcyBiZWxvdyBieSBydW5uaW5nIHRoZSBmb2xsb3dpbmcgY2h1bmsgKGFzc3VtaW5nIHRoZSBmaWxlICAiSW5zdWxhdGluZ0RhdGEuUmRhdGEiIGlzIHNhdmVkIGluIHRoZSBzYW1lIGRpcmVjdG9yeSBhcyB0aGUgLlJtZCAgd29ya3NoZWV0KS4KCiMjIFF1ZXN0aW9uIDEgVGhlIHRpbWluZyBvZiBwcm9kdWN0aW9uIHJ1bnMgKFNoZWF0aGVyLCAyMDA5KQoKVGhlIG9yaWdpbmFsIGRhdGEgYXJlIGluIHRoZSBmb3JtIG9mIHRoZSB0aW1lIHRha2VuIChpbiBtaW51dGVzKSBmb3IgYSBwcm9kdWN0aW9uIHJ1biwgJFkkLCBhbmQgdGhlIG51bWJlciBvZiBpdGVtcyBwcm9kdWNlZCwKJFgkLCBmb3IgMjAgcmFuZG9tbHkgc2VsZWN0ZWQgb3JkZXJzIGFzIHN1cGVydmlzZWQgYnkgdGhyZWUgbWFuYWdlcnMuIEF0IHRoaXMgc3RhZ2Ugd2Ugc2hhbGwgb25seSBjb25zaWRlciB0aGUgZGF0YSBmb3Igb25lIG9mIHRoZSBtYW5hZ2Vycy4KCihhKS4gT3BlbiB0aGUgRXhjZWwgZmlsZSAqcHJvZHVjdGlvbi50eHQqLiBDb25zdHJ1Y3QgYSBzY2F0dGVycGxvdCBvZiBwcm9kdWN0aW9uIHJ1biwgJFkkLCBhbmQgdGhlIG51bWJlciBvZiBpdGVtcyBwcm9kdWNlZCwgJFgkLiBGaXQgdGhlIGxlYXN0IHNxdWFyZXMgbGluZSB0byB0aGUgZGF0YSB1c2luZyBSLiBFeHBsYWluIHRoZSBmaXR0ZWQgbW9kZWwsIGJ5IGludGVycHJldGluZyB0aGUgc2xvcGUgYW5kIGludGVyY2VwdC4KCmBgYHtyfQpwcm9kdWN0aW9uPXJlYWQudGFibGUoInByb2R1Y3Rpb24udHh0IiwgaGVhZGVyPVQpCnByb2R1Y3Rpb24KYGBgCgpgYGB7cn0KcHJvZC5sbT1sbShSdW5UaW1lIH4gUnVuU2l6ZSwgZGF0YT1wcm9kdWN0aW9uKSAjIyB0aGUgTFMgbGluZQpwcm9kLmxtMT1sbShSdW5UaW1lIH4gUnVuU2l6ZSwgZGF0YT1wcm9kdWN0aW9uKQpwbG90KFJ1blRpbWUgfiBSdW5TaXplLCBkYXRhPXByb2R1Y3Rpb24sIHhsYWI9IlJ1biBTaXplIiwgeWxhYj0iUnVuIFRpbWUiKQphYmxpbmUocHJvZC5sbSkKc3VtbWFyeShwcm9kLmxtKQpgYGAKClRoZSBlcXVhdGlvbiBvZiB0aGUgbGVhc3Qgc3F1YXJlcyBsaW5lIG9mIGJlc3QgZml0IGlzCgokJHkgPSAxNDkuNyArIDAuMjZ4LiQkCgpUaGUgaW50ZXJjZXB0IGlzIDE0OS43LCB3aGljaCBpcyB3aGVyZSB0aGUgbGluZSBvZiBiZXN0IGZpdCBjcm9zc2VzIHRoZSBydW4gdGltZSBheGlzLiBUaGUKaW50ZXJjZXB0IGluIHRoZSBtb2RlbCBoYXMgdGhlIGZvbGxvd2luZyBpbnRlcnByZXRhdGlvbjogZm9yIGFueSBwcm9kdWN0aW9uIHJ1biwgdGhlCmF2ZXJhZ2Ugc2V0IHVwIHRpbWUgaXMgMTQ5LjcgbWludXRlcy4KClRoZSBzbG9wZSBvZiB0aGUgbGluZSBpcyAwLjI2LiBUaHVzLCB3ZSBzYXkgdGhhdCBlYWNoCmFkZGl0aW9uYWwgdW5pdCB0byBiZSBwcm9kdWNlZCBpcyBwcmVkaWN0ZWQgdG8gYWRkIDAuMjYgbWludXRlcyB0byB0aGUgcnVuIHRpbWUuIAoKVGhlIHZhbHVlIG9mICRSXjI9ICAwLjczMDIkIHdoaWNoIGltcGxpZXMgdGhhdCA3My4wMiUgb2YgdGhlIGluZm9ybWF0aW9uICh2YXJpYXRpb24pIGluIFJ1biBUaW1lIGlzIGV4cGxhaW5lZCBieSB0aGUgbGVhc3Qgc3F1YXJlcyByZWdyZXNzaW9uIGxpbmUsIHN1Z2dlc3RpbmcgdGhhdCB0aGUgbW9kZWwgaXMgYSBnb29kIG1vZGVsLgoKKGIpLiAgQ29uc3RydWN0IHJlc2lkdWFsIGRpYWdub3N0aWMgcGxvdHMsIGFuZCBhc3Nlc3Mgd2hldGhlciB5b3UgdGhpbmsgdGhhdCB0aGUgYXNzdW1wdGlvbnMgZm9yIGxpbmVhciByZWdyZXNzaW9uIGhhdmUgYmVlbiBzYXRpc2ZpZWQuIFlvdSBjYW4gdXNlIHRoZSBmdW5jdGlvbiBgcnN0dWRlbnRgIChvciBgcnN0YW5kYXJkYCkgdG8gZmlyc3Qgc3RhbmRhcmRpemUgdGhlIHJlc2lkdWFscy4KCgpGaXJzdCwgd2UgbWFudWFsbHkgY2hlY2sgdGhlICpub3JtYWxpdHkgdGhyb3VnaCBoaXN0b2dyYW1zIGFuZCBRUS1wbG90cyBvZiByZXNpZHVhbHMgYW5kIHN0YW5kYXJkaXNlZCByZXNpZHVhbHMuKgoKYGBge3J9Cm5hbWVzKHByb2QubG0pICAjIyBjaGVja2luZyB0aGUgb3V0cHV0IG9mIHRoZSBmaXR0ZWQgbW9kZWwsIHJlc2lkdWFscwpyZXM9cHJvZC5sbSRyZXNpZHVhbHMKc3RkLnJlcz1yc3RhbmRhcmQocHJvZC5sbSkgICMjIHN0YW5kYXJkaXNlZCByZXNpZHVhbHMKcGFyKG1mcm93PWMoMiwyKSkgICMjIHBsb3R0aW5nIDQgcGxvdHMgdG8gY2hlY2sgbm9ybWFsaXR5Cmhpc3QocmVzKQpoaXN0KHN0ZC5yZXMpCnFxbm9ybShyZXMpCnFxbGluZShyZXMpCnFxbm9ybShzdGQucmVzKQpxcWxpbmUoc3RkLnJlcykKcGFyKG1mcm93PWMoMSwxKSkKYGBgCgpGcm9tIHRoZSBhYm92ZSBoaXN0b2dyYW1zIGFuZCBRUS1wbG90cywgdGhlIG5vcm1hbGl0eSBpcyBzYXRpc2ZpZWQuCgpgYGB7cn0KcGFyKG1mcm93PWMoMiwyKSkKcGxvdChyZXMsIHhsYWI9IlRpbWUiLCB5bGFiPSJSZXNpZHVhbHMiKSAjIyBSZXNpZHVhbHMgdnMgVGltZQpwbG90KHN0ZC5yZXMseGxhYj0iVGltZSIsIHlsYWI9IlN0YW5kYXJkaXNlZCBSZXNpZHVhbHMiKQpwbG90KHByb2R1Y3Rpb24kUnVuU2l6ZSxyZXMsIHhsYWI9IlJ1biBTaXplIiwgeWxhYj0iUmVzaWR1YWxzIikgIyBSZXNpZHVhbHMgdnMgeApwbG90KHByb2R1Y3Rpb24kUnVuU2l6ZSxzdGQucmVzLCAgeGxhYj0iUnVuIFNpemUiLCB5bGFiPSJTdGFuZGFyZGlzZWQgUmVzaWR1YWxzIikKYGBgCgogICAgIC0gVGhlIG5leHQgcmVzaWR1YWwgYW5hbHlzaXMgaXMgdG8gY2hlY2sgYWJvdXQgcmFuZG9tbmVzcyAoaW5kZXBlbmRlbmNlKSBhbmQgY29uc3RhbnQgdmFyaWFuY2UuIFdlIHBsb3QgYm90aAogICAgIHJlc2lkdWFscyBhbmQgc3RhbmRhcmRpc2VkIHJlc2lkdWFscyBhZ2FpbnN0IHRpbWUgKHRvcCBsZWZ0IGFuZCB0b3AgcmlnaHQpLiBGcm9tIHRoZXNlIHBsb3RzIHdlIGNhbiBjb25maXJtIHRoZQogICAgIHRoZSByZXNpZHVhbCBhcmUgcmFuZG9tIHNjYXR0ZXJlZCB3aXRoIG5vIHBhdHRlcm4gd2hhdHNvZXZlci4KCiAgICAgLSBUaGUgYm90dG9tIGxlZnQgcGxvdCBzaG93cyB0aGUgcmVzaWR1YWxzIGFnYWluc3QgUnVuIFNpemUgdG8gY2hlY2sgcmFuZG9tbmVzcyAobm8gcGF0dGVybikgYW5kIGNvbnN0YW50CiAgICAgdmFyaWFuY2UuIFRoZSBib3R0b20gcmlnaHQgcGxvdCBwcm92aWRlcyB0aGUgc3RhbmRhcmRpc2VkIHJlc2lkdWFscyBhZ2FpbnN0IGZpdHRlZCB2YWx1ZXMgdG8gY2hlY2sgcmFuZG9tbmVzcyAobm8KICAgICBwYXR0ZXJuKSBhbmQgY29uc3RhbnQgdmFyaWFuY2UuIEJvdGggcGxvdHMgY29uZmlybSByYW5kb21uZXNzIGFuZCBjb25zdGFudCB2YXJpYW5jZS4KCihjKS4gVXNpbmcgdGhlIGZpdHRlZCBtb2RlbC4KCmBgYHtyfQpwYXIobWZyb3c9YygyLDIpKSAjIHRvIHZpZXcgMngyIHBsb3RzCnBsb3QocHJvZC5sbSkKcGxvdChwcm9kLmxtMSkKYGBgCgpUaGUgZmlndXJlIGFib3ZlIHByb3ZpZGVzIGRpYWdub3N0aWMgcGxvdHMgcHJvZHVjZWQgYnkgUiB3aGVuIHRoZSBjb21tYW5kIGBwbG90KHByb2QubG0pYCBpcyB1c2VkLCB3aGVyZSBgcHJvZC5sbWAgaXMgdGhlIHJlc3VsdCBvZiB0aGUg4oCcbG3igJ0gY29tbWFuZC4gCgogICAgKyBUaGUgdG9wIGxlZnQgcGxvdCBzaG93cyB0aGUgcmVzaWR1YWxzIGFnYWluc3QgZml0dGVkIHZhbHVlcyB0byBjaGVjayByYW5kb21uZXNzIChubyBwYXR0ZXJuKSBhbmQgbGluZWFyaXR5LiAKCiAgICArIFRoZSBib3R0b20gbGVmdCBwcm92aWRlcyB0aGUgc3RhbmRhcmRpc2VkIHJlc2lkdWFscyBhZ2FpbnN0IGZpdHRlZCB2YWx1ZXMgdG8gY2hlY2sgcmFuZG9tbmVzcyAobm8gcGF0dGVybikgYW5kIGNvbnN0YW50IHZhcmlhbmNlLiBUaGUgc21vb3RoaW5nIGN1cnZlIHVzaW5nIHN0YW5kYXJkaXNlZCByZXNpZHVhbHMgaXMgYWxtb3N0IGZsYXQgKGkuZSBjb25zdGFudCkgdG8gY29uZmlybSByYW5kb21uZXNzIGFuZCBjb25zdGFudCB2YXJpYW5jZS4KCiAgICArIFRoZSB0b3AgcmlnaHQgcGxvdCBpcyBhIG5vcm1hbCBR4oCTUSBwbG90LiBNb3N0IG9mIHRoZSBvYnNlcnZhdGlvbnMgbGllIGFyb3VuZCB0aGUgc3RyYWlnaHQgbGluZSwgY29uZmlybWluZyBOb3JtYWxpdHkuCgogICAgKyBUaGUgYm90dG9tIHJpZ2h0IHBsb3Qgb2Ygc3RhbmRhcmRpemVkIHJlc2lkdWFscyBhZ2FpbnN0IGxldmVyYWdlIGVuYWJsZXMgb25lCiAgICB0byByZWFkaWx5IGlkZW50aWZ5IGFueSDigJhiYWTigJkgbGV2ZXJhZ2UgcG9pbnRzLiAKCiAgICAgICAtIFJlY2FsbCB0aGF0IHRoZSBydWxlIGZvciBzaW1wbGUgbGluZWFyIHJlZ3Jlc3Npb24gZm9yIGNsYXNzaWZ5aW5nIGEgcG9pbnQgYXMgYSBsZXZlcmFnZQogICAgICAgcG9pbnQgaXMgaWYgbGV2ZXJhZ2UgJGhfe2lpfSA+IDQvIG4uJCBBcyAkbj0yMCQsIHRoZSBydWxlIGlzICRoX3tpaX0gPiAwLjIuJCBBcyBsZXZlcmFnZSAkaF97aWl9JCBpbiB0aGUgYWJvdmUKICAgICAgIGJvdHRvbSByaWdodCBpcyBsZXNzIHRoYW4gMC4yLCB0aGVuIHRoZXJlIGlzIG5vIGxldmVyYWdlIHBvaW50cy4KCiAgICAgICAtIFJlY2FsbCB0aGF0IHdlIGNsYXNzaWZ5IHBvaW50cyBhcyBvdXRsaWVycyBpZiB0aGVpciBzdGFuZGFyZGl6ZWQgcmVzaWR1YWxzIGhhdmUgYWJzb2x1dGUgdmFsdWUgZ3JlYXRlciB0aGFuCiAgICAgICAyLiBBbGwgdGhlIHJlc2lkdWFscyBhcmUgd2l0aGluICgtMiwyKSwgdGhlcmVmb3JlIG5vIG91dGxpZXJzIGJlaW5nIGRldGVjdGVkLgoKCiMjIFF1ZXN0aW9uIDIgVGhlIGludm9pY2VzIGRhdGEgKFNoZWF0aGVyLCAyMDA5KQoKVGhlIG1hbmFnZXIgb2YgdGhlIHB1cmNoYXNpbmcgZGVwYXJ0bWVudCBvZiBhIGxhcmdlIGNvbXBhbnkgd291bGQgbGlrZSB0bwpkZXZlbG9wIGEgcmVncmVzc2lvbiBtb2RlbCB0byBwcmVkaWN0IHRoZSBhdmVyYWdlIGFtb3VudCBvZiB0aW1lIGl0IHRha2VzIHRvIHByb2Nlc3MgYSBnaXZlbiBudW1iZXIgb2YgaW52b2ljZXMuIE92ZXIgYSAzMC1kYXkgcGVyaW9kLCBkYXRhIGFyZSBjb2xsZWN0ZWQgb24gdGhlIG51bWJlciBvZiBpbnZvaWNlcyBwcm9jZXNzZWQgYW5kIHRoZSB0b3RhbCB0aW1lIHRha2VuIChpbiBob3VycykuIFRoZSBkYXRhIGFyZSBhdmFpbGFibGUgaW4gdGhlIGZpbGUgKmludm9pY2VzLnR4dC4qIAoKQ29tcGxldGUgdGhlIGZvbGxvd2luZyB0YXNrcy4KCihhKS4gRml0IHRoZSBsZWFzdCBzcXVhcmVzIGxpbmUgdG8gdGhlIGRhdGEgdXNpbmcgUi4gRXhwbGFpbiB0aGUgZml0dGVkIG1vZGVsLCBieSBpbnRlcnByZXRpbmcgdGhlIHNsb3BlIGFuZCBpbnRlcmNlcHQuCgpgYGB7cn0KaW52b2ljZXM9cmVhZC50YWJsZSgiaW52b2ljZXMudHh0IiwgaGVhZGVyPVQpClZpZXcoaW52b2ljZXMpCmBgYAoKYGBge3J9Cmludi5sbT1sbShUaW1lIH4gSW52b2ljZXMsIGRhdGE9aW52b2ljZXMpCnBsb3QoVGltZSB+IEludm9pY2VzLCBkYXRhPWludm9pY2VzKQphYmxpbmUoaW52LmxtKQpzdW1tYXJ5KGludi5sbSkKYGBgCgpUaGUgZXF1YXRpb24gb2YgdGhlIGxlYXN0IHNxdWFyZXMgbGluZSBvZiBiZXN0IGZpdCBpcwoKJCQgVGltZT0gMC42NDIgKyAwLjAxMSBJbnZvaWNlcyAuJCQKClRoZSBpbnRlcmNlcHQgaXMgMC42NDIsIHdoaWNoIGlzIG5vdCBpbnRlcnByZXRhYmxlIGZvciBubyBpbnZvaWNlcy4KClRoZSBzbG9wZSBvZiB0aGUgbGluZSBpcyAwLjAxMS4gVGh1cywgd2Ugc2F5IGZvciB0aGF0IGZvciBlYWNoCmFkZGl0aW9uYWwgaW52b2ljZSwgdGhlIGF2ZXJhZ2UgYW1vdW50IG9mIHRpbWUgaXQgdGFrZXMgdG8gcHJvY2VzcyBpbmNyZWFzZXMgYnkgMC4wMTEgaG91ci4KCihiKS4gQ29uc3RydWN0IHJlc2lkdWFsIGRpYWdub3N0aWMgcGxvdHMsIGFuZCBhc3Nlc3Mgd2hldGhlciB5b3UgdGhpbmsgdGhhdCB0aGUgYXNzdW1wdGlvbnMgZm9yIGxpbmVhciByZWdyZXNzaW9uIGhhdmUgYmVlbiBzYXRpc2ZpZWQuIFlvdSBjYW4gdXNlIHRoZSBmdW5jdGlvbiBgcnN0dWRlbnRgIChvciBgcnN0YW5kYXJkYCkgdG8gZmlyc3Qgc3RhbmRhcmRpemUgdGhlIHJlc2lkdWFscy4KCkZpcnN0LCB3ZSBjaGVjayB0aGUgbm9ybWFsaXR5IHRocm91Z2ggaGlzdG9ncmFtcyBhbmQgUVEtcGxvdHMgb2YgcmVzaWR1YWxzIGFuZCBzdGFuZGFyZGlzZWQgcmVzaWR1YWxzLgoKYGBge3J9Cm5hbWVzKGludi5sbSkgICMjIGNoZWNraW5nIHRoZSBvdXRwdXQgb2YgdGhlIGZpdHRlZCBtb2RlbCwgcmVzaWR1YWxzCnJlcz1pbnYubG0kcmVzaWR1YWxzCnN0ZC5yZXM9cnN0YW5kYXJkKGludi5sbSkgICMjIHN0YW5kYXJkaXNlZCByZXNpZHVhbHMKcGFyKG1mcm93PWMoMiwyKSkgICMjIHBsb3R0aW5nIDQgcGxvdHMgdG8gY2hlY2trIG5vcm1hbGl0eQpoaXN0KHJlcykKaGlzdChzdGQucmVzKQpxcW5vcm0ocmVzKQpxcWxpbmUocmVzKQpxcW5vcm0oc3RkLnJlcykKcXFsaW5lKHN0ZC5yZXMpCnBhcihtZnJvdz1jKDEsMSkpCmBgYAoKVGhlIGhpc3RvZ3JhbXMgc2hvdyBiaW1vZGFsaXRpZXMuIEZyb20gdGhlIFFRLXBsb3RzLCB0aGUgbm9ybWFsaXR5IHNlZW1zIHRvIGJlIHNhdGlzZmllZCwgZXhjZXB0IDEgcG9pbnQgYXQgdGhlIHRvcCBhbmQgMSBwb2ludCBhdCB0aGUgYm90dG9tIHJlc3BlY3RpdmVseS4KCmBgYHtyfQpwYXIobWZyb3c9YygyLDIpKQpwbG90KHJlcywgeGxhYj0iVGltZSIsIHlsYWI9IlJlc2lkdWFscyIpCnBsb3Qoc3RkLnJlcyx4bGFiPSJUaW1lIiwgeWxhYj0iU3RhbmRhcmRpc2VkIFJlc2lkdWFscyIpCnBsb3QocmVzLCBpbnZvaWNlcyRJbnZvaWNlcywgeGxhYj0iSW52b2ljZXMiLCB5bGFiPSJSZXNpZHVhbHMiKQpwbG90KHN0ZC5yZXMsIGludm9pY2VzJEludm9pY2VzLCAgeGxhYj0iSW52b2ljZXMiLCB5bGFiPSJTdGFuZGFyZGlzZWQgUmVzaWR1YWxzIikKYGBgCgpUaGUgbmV4dCByZXNpZHVhbCBhbmFseXNpcyBpcyB0byBjaGVjayBhYm91dCByYW5kb21uZXNzIChpbmRlcGVuZGVuY2UpIGFuZCBjb25zdGFudCB2YXJpYW5jZS4gV2UgcGxvdCBib3RoIHJlc2lkdWFscyBhbmQgc3RhbmRhcmRpc2VkIHJlc2lkdWFscyBhZ2FpbnN0IHRpbWUgKHRvcCBsZWZ0IGFuZCB0b3AgcmlnaHQpLiBGcm9tIHRoZXNlIHBsb3RzIHdlIGNhbiBzZWUgYSBiaXQgb2YgaW5jcmVhc2luZyBwYXR0ZXJuLCBzbWFsbCByZXNpZHVhbHMgd2l0aGluIDAtMTUgYW5kIHRoZW4gbGFyZ2VyIHJlc2lkdWFscyB3aXRoaW4gMTUtMzAuCgpUaGUgYm90dG9tIGxlZnQgcGxvdCBzaG93cyB0aGUgcmVzaWR1YWxzIGFnYWluc3QgSW52b2ljZXMgdG8gY2hlY2sgcmFuZG9tbmVzcyAobm8gcGF0dGVybikgYW5kIGNvbnN0YW50IHZhcmlhbmNlLiBUaGUgYm90dG9tIHJpZ2h0IHBsb3QgcHJvdmlkZXMgdGhlIHN0YW5kYXJkaXNlZCByZXNpZHVhbHMgYWdhaW5zdCBmaXR0ZWQgdmFsdWVzIHRvIGNoZWNrIHJhbmRvbW5lc3MgKG5vIHBhdHRlcm4pIGFuZCBjb25zdGFudCB2YXJpYW5jZS4gQm90aCBwbG90cyBzaG93IGEgYml0IG9mIHBhdHRlcm4gYmV0d2VlbiBuZWdhdGl2ZSBhbmQgcG9zaXRpdmUgSW52b2ljZXMuCgooYykuIFBlcmZvcm0gZGlhZ25vc3RpYyBjaGVja2luZyBmb3IgdGhlIGZpdHRlZCBtb2RlbCBpbiAoYSkgdXNpbmcgInBsb3QoZmlsZS5sbSkuIiBJbnRlcnByZXQgdGhlIG91dHB1dHMuCgoKYGBge3J9CnBhcihtZnJvdz1jKDIsMikpCnBsb3QoaW52LmxtKQpgYGAKCgorIFRoZSB0b3AgbGVmdCBwbG90IHNob3dzIHRoZSByZXNpZHVhbHMgYWdhaW5zdCBmaXR0ZWQgdmFsdWVzIHRvIGNoZWNrIHJhbmRvbW5lc3MgKG5vIHBhdHRlcm4pIGFuZCBsaW5lYXJpdHkuIAoKKyBUaGUgYm90dG9tIGxlZnQgcHJvdmlkZXMgdGhlIHN0YW5kYXJkaXNlZCByZXNpZHVhbHMgYWdhaW5zdCBmaXR0ZWQgdmFsdWVzIHRvIGNoZWNrIHJhbmRvbW5lc3MgKG5vIHBhdHRlcm4pIGFuZCBjb25zdGFudCB2YXJpYW5jZS4gVGhlIHNtb290aGluZyBjdXJ2ZSB1c2luZyBzdGFuZGFyZGlzZWQgcmVzaWR1YWxzIGlzIGEgY3VydmUgd2hpY2ggbWVhbnMgdGhhdCBpbmRlcGVuZGVuY2UgYW5kIGNvbnN0YW50IHZhcmlhbmNlIG1heSBub3QgYmUgc2F0aXNmaWVkLgoKKyBUaGUgdG9wIHJpZ2h0IHBsb3QgaXMgYSBub3JtYWwgUeKAk1EgcGxvdC4gTW9zdCBvZiB0aGUgb2JzZXJ2YXRpb25zIGxpZSBhcm91bmQgdGhlIHN0cmFpZ2h0IGxpbmUgZXhjZXB0IHRoZSB0d28gcG9pbnRzLCBjb25maXJtaW5nIE5vcm1hbGl0eS4KCisgVGhlIGJvdHRvbSByaWdodCBwbG90IG9mIHN0YW5kYXJkaXplZCByZXNpZHVhbHMgYWdhaW5zdCBsZXZlcmFnZSBlbmFibGVzIG9uZQp0byByZWFkaWx5IGlkZW50aWZ5IGFueSDigJhiYWTigJkgbGV2ZXJhZ2UgcG9pbnRzLiAKCiAgICAgICAtIFJlY2FsbCB0aGF0IHRoZSBydWxlIGZvciBzaW1wbGUgbGluZWFyIHJlZ3Jlc3Npb24gZm9yIGNsYXNzaWZ5aW5nIGEgcG9pbnQgYXMgYSBsZXZlcmFnZQogICAgICAgcG9pbnQgaXMgaWYgbGV2ZXJhZ2UgJGhfe2lpfSA+IDQvIG4uJCBBcyAkbj0zMCQsIHRoZSBydWxlIGlzICRoX3tpaX0gPiAwLjEzLiQgQXMgbGV2ZXJhZ2UgJGhfe2lpfSQgaW4gdGhlIGFib3ZlCiAgICAgICBib3R0b20gcmlnaHQgcGxvdCBoYXMgb25lIHBvaW50IHdpdGggJGhfe2lpfSA+IDAuMTMkICwgdGhlbiB0aGVyZSBpcyBvbmUgbGV2ZXJhZ2UgcG9pbnQuCgogICAgICAtIFJlY2FsbCB0aGF0IHdlIGNsYXNzaWZ5IHBvaW50cyBhcyBvdXRsaWVycyBpZiB0aGVpciBzdGFuZGFyZGl6ZWQgcmVzaWR1YWxzIGhhdmUKICAgICAgYWJzb2x1dGUgdmFsdWUgZ3JlYXRlciB0aGFuIDIuIEFsbCB0aGUgcmVzaWR1YWxzIGFyZSB3aXRoaW4gKC0yLDIpLCB0aGVyZWZvcmUgbm8gb3V0bGllcnMgYmVpbmcgZGV0ZWN0ZWQuIFRoZQogICAgICBhYm92ZSBsZXZlcmFnZSBwb2ludCBpcyBhIGBnb29kYCBsZXZlcmFnZSBwb2ludC4KCihkKS4gVXNlIHRoZSBmdW5jdGlvbiBgaW5mbHVlbmNlLm1lYXN1cmVzYCB0byBleHBsb3JlIG1lYXN1cmVzIG9mIGxldmVyYWdlIGFuZCBDb29rJ3MgZGlzdGFuY2UuICAgCgpgYGB7cn0KIyBjaGVjayBoZWxwIGZ1bmN0aW9uIGZpcnN0Ckludi5pbmZsPC1pbmZsdWVuY2UubWVhc3VyZXMoaW52LmxtKQpJbnYuaW5mbAojaGVhZChJbnYuaW5mbCRpbmZtYXQpCmBgYAoKUG9pbnRzIGluY3JlYXNlIGluIGluZmx1ZW5jZSB0byB0aGUgZXh0ZW50IHRoYXQgdGhleSBsaWUgb24gdGhlaXIgb3duLCBhIGxvbmcgd2F5IGZyb20gdGhlIG1lYW4gb2YgJHgkIGFuZCB0aGUgYnVsayBvZiB0aGUgZGF0YS4gVGhlIGNvbHVtbiAiaGF0IiBpbiB0aGUgYWJvdmUgaXMgdGhlIGNvbW1vbmVzdCBtZWFzdXJlIG9mIHRoaXMgbGV2ZXJhZ2UgYW5kIGlzIGRlZmluZWQgYnk6CgokJGhfaSA9IFxmcmFjezF9e259ICsgXGZyYWN7KHhfaS1cYmFye3h9KV4yfXtcc3VtKHhfaiAtXGJhcnt4fSleMn0gLiQkCgoKQ29va+KAmXMgZGlzdGFuY2UgKHRoZSBjb2x1bW4gImNvb2suZCIgaW4gdGhlIGFib3ZlKSBpcyBvbmUgbWVhc3VyZSBvZiBpbmZsdWVuY2U6IGZvciBlYWNoIHBvaW50LCBpdCBjb21iaW5lcyB0aGUgc2l6ZSBvZiBpdHMgcmVzaWR1YWwgYWxvbmcgd2l0aCBhIG1lYXN1cmUgb2YgdGhlIGxldmVyYWdlLiBBbiBhcHByb3hpbWF0ZSBjdXRvZmYgaXMgJDQvKG4tMikkLCBidXQgaW4gcHJhY3RpY2UgaXQgaXMgaW1wb3J0YW50IHRvIGxvb2sgZm9yIGdhcHMgaW4gdmFsdWVzIG9mIENvb2vigJlzIGRpc3RhbmNlIGluc3RlYWQgb2YganVzdCB3aGV0aGVyIG9yIG5vdCB0aGUgdmFsdWVzIGV4Y2VlZCB0aGUgY3V0b2ZmLgoKVGhlcmUgYXJlIDIgZnVuY3Rpb25zIHdoaWNoIGNhbiBhbHNvIGJlIHVzZWQgdG8gY2FsY3VsYXRlIHRoZXNlIG1lYXN1cmVzIGRpcmVjdGx5OiBgaGF0dmFsdWVzYCBhbmQgYGNvb2tzLmRpc3RhbmNlYC4KCmBgYHtyfQpMZXZlcmFnZS5pbnY8LWhhdHZhbHVlcyhpbnYubG0pCkNvb2tzLkRpc3QuaW52PC1jb29rcy5kaXN0YW5jZShpbnYubG0pCkludiA8LSBpbnZvaWNlcyRJbnZvaWNlcwpgYGAKCgpgYGB7ciwgZmlnMywgZmlnLndpZHRoID0gNSwgZmlnLmFzcCA9IC41fQojIHBsb3R0aW5nIHRoZSBpbmZsdWVuY2UgbWVhc3VyZXMgYWdhaW5zdCB0aGVpciB4IHZhbHVlIC0gSW52b2ljZXMgCm49MzAKcGxvdChMZXZlcmFnZS5pbnZ+SW52KQphYmxpbmUoaD00L24sIGNvbD0zKQpwbG90KENvb2tzLkRpc3QuaW52fkludikKYWJsaW5lKGg9NC8obi0yKSwgY29sPTIpCmBgYAoKLSBSZWNhbGwgdGhhdCB3ZSBjbGFzc2lmeSBwb2ludHMgYXMgb3V0bGllcnMgaWYgdGhlaXIgc3RhbmRhcmRpemVkIHJlc2lkdWFscyBoYXZlCmFic29sdXRlIHZhbHVlIGdyZWF0ZXIgdGhhbiAyLiBBbGwgdGhlIHJlc2lkdWFscyBhcmUgd2l0aGluICgtMiwyKSwgdGhlcmVmb3JlIG5vIG91dGxpZXJzIGJlaW5nIGRldGVjdGVkLiBUaGUgYWJvdmUgbGV2ZXJhZ2UgcG9pbnQgaXMgYSBgZ29vZGAgbGV2ZXJhZ2UgcG9pbnQuCgotIENvb2tzIERpc3RhbmNlIGlkZW50aWZpZXMgb25lIHBvdGVudGlhbCBvdXRsaWVyLCBvYnNlcnZhdGlvbiBudW1iZXIgMzAuIEhvd2V2ZXIsIGl0IGlzIGltcG9ydGFudCB0byBsb29rIGZvciBnYXBzIGluIHZhbHVlcyBvZiBDb29r4oCZcyBkaXN0YW5jZSBpbnN0ZWFkIG9mIGp1c3Qgd2hldGhlciBvciBub3QgdGhlIHZhbHVlcyBleGNlZWQgdGhlIGN1dG9mZi4KCgoKYGBge3J9CnNvcnQoTGV2ZXJhZ2UuaW52KQpgYGAKCmBgYHtyfQpzb3J0KENvb2tzLkRpc3QuaW52KQpgYGAKCgojIyBRdWVzdGlvbiAzIChGcm9tIFdlaXNiZXJnLCBTLiAoMjAwNSkuICpBcHBsaWVkIExpbmVhciBSZWdyZXNzaW9uKiwgM3JkIGVkaXRpb24uIE5ldyBZb3JrOiBXaWxleSkKCkluIHRoaXMgcXVlc3Rpb24sIHlvdSB3aWxsIGJlIGxlYXJuaW5nIHRoZSBSIGNvZGUgaW4gbW9yZSBkZXRhaWwgdG8gcHJvdmlkZSBiZXR0ZXIgdmlzdWFsaXNhdGlvbiB3aGljaCBtYXkgYmUgbmVlZGVkIGZvciB5b3VyIHByb2plY3QuIEZ1cnRoZXJtb3JlLCB0aGUgQU5PVkEgaXMgZXhwbGFpbmVkIGluIG1vcmUgZGV0YWlsIGZvbGxvd2luZyB0aGUgbGVjdHVyZSAocGFydCBjKS4KClRoZSAqUiogZGF0YSBmaWxlIGBXaW5kLlJEYXRhYCBjb250YWlucyBhIGRhdGEgZnJhbWUgKGB3bTFgKSBjb250YWluaW5nIHdpbmQgc3BlZWQgZGF0YSAoaW4gbS9zKSBhdCB0d28gc2l0ZXM6IGEgcmVmZXJlbmNlIHNpdGUgKGBSc3BkYCkgYW5kIGEgY2FuZGlkYXRlIHNpdGUgKGBDU3BkYCkuIERhdGEgd2VyZSBjb2xsZWN0ZWQgZXZlcnkgNiBob3VycyBmb3IgdGhlIHllYXIgMjAwMiBleGNlcHQgaW4gdGhlIG1vbnRoIG9mIE1heS4gVGhlIG9iamVjdGl2ZSBpcyB0byBiZSBhYmxlIHRvIGRldGVybWluZSB3aGV0aGVyIHdpbmQgc3BlZWQgYXQgdGhlIHJlZmVyZW5jZSBzaXRlLCB3aGljaCBoYXMgcGVybWFuZW50IHdpbmQgc3BlZWQgbW9uaXRvcmluZyBlcXVpcG1lbnQsIGNhbiBiZSB1c2VkIHRvIHByZWRpY3QgdGhlIHdpbmQgc3BlZWQgYXQgdGhpcyBjYW5kaWRhdGUgc2l0ZSBpbiB0aGUgZnV0dXJlIGluIG9yZGVyIHRvIGRldGVybWluZSB3aGV0aGVyIHRvIHBsYWNlIGEgc21hbGwgd2luZCBmYXJtIHRoZXJlLgoKYGBge3J9CiMgTG9hZCB0aGUgd29ya3Nob3AgZGF0YSBoZXJlCmxvYWQoIldpbmQuUkRhdGEiKQpucm93KCdXaW5kLlJEYXRhJykKYGBgCgoKYS4gRHJhdyBhIHNjYXR0ZXJwbG90IG9mIHRoZSByZXNwb25zZSBgQ1NwZGAgYWdhaW5zdCB0aGUgcHJlZGljdG9yIGBSU3BkYCBhbmQgbGFiZWwgaXQgYXBwcm9wcmlhdGVseS4gCgpgYGB7ciBQbG90RGF0YSwgZmlnLmhlaWdodD03fQpwYXIocHR5ID0gInMiKSAjIEEgZ3JhcGhpY2FsIHBhcmFtZXRlciB0aGF0IHNldHMgdGhlIFBsb3RUWXBlIHRvICJzcXVhcmUiCgojIFRoZSBzeW50YXggb2YgdGhlIHBsb3Qgc3RhdGVtZW50IHNheXMgInBsb3QgQ1NwZCBhZ2FpbnN0IFJTcGQgYnV0IGV4dHJhY3QgdGhlbSAKIyBmcm9tIHRoZSBkYXRhIGZyYW1lIHdtMS4gVGhlIHhsaW0gYW5kIHlsaW0gYXJndW1lbnRzIGFyZSB0aGUgc2FtZSAtIHRoZSByYW5nZSAKIyBvZiBhbGwgdGhlIGRhdGEuIApwbG90KENTcGQgfiBSU3BkLCBkYXRhID0gd20xLCAKICAgICB4bGFiID0gIldpbmQgc3BlZWQgYXQgcmVmZXJlbmNlIHNpdGUgKG0vcykiLCAKICAgICB5bGFiID0gIldpbmQgc3BlZWQgYXQgY2FuZGlkYXRlIHNpdGUgKG0vcykiLAogICAgIG1haW4gPSAiV2luZCBzcGVlZHMgYXQgcmVmZXJlbmNlIGFuZCBjYW5kaWRhdGUgc2l0ZXMiLAogICAgIHhsaW0gPSByYW5nZShjKHdtMSRDU3BkLCB3bTEkUlNwZCkpLCB5bGltID0gYyhyYW5nZShjKHdtMSRDU3BkLCB3bTEkUlNwZCkpKSkgCgpucm93KHdtMSkKYGBgCgpGaXQgYSBzaW1wbGUgbGluZWFyIG1vZGVsIHRvIHRoZXNlIGRhdGEsIGFuZCBwcmVzZW50IHRoZSBhcHByb3ByaWF0ZSByZWdyZXNzaW9uIHN1bW1hcmllcy4gUGxvdCB0aGUgZml0dGVkIGxpbmUgb250byB0aGUgcGxvdCBpbiAoYSkuCgpgYGB7cn0KIyBOb3RpY2UgdGhlIHNpbWlsYXJpdHkgd2l0aCB0aGUgcGxvdCBzdGF0ZW1lbnQgYWJvdmUKV2luZC5sbSA8LSBsbShDU3BkIH4gUlNwZCwgZGF0YSA9IHdtMSkKIyBIZXJlIGFyZSB0aGUgY29udGVudHMgb2YgdGhlIG9iamVjdCBXaW5kLmxtOgpuYW1lcyhXaW5kLmxtKQojIGFuZCBoZXJlJ3Mgc29tZSBiYXNpYyBvdXRwdXQ6CldpbmQubG0KCiMgQSBiaXQgbW9yZSBjb21lcyBmcm9tIHRoZSBzdW1tYXJ5KCkgZnVuY3Rpb246CnN1bW1hcnkoV2luZC5sbSkKYGBgCgogICpUbyBwbG90IHRoZSBmaXR0ZWQgbGluZSBvbnRvIGFuIGV4aXN0aW5nIHBsb3QgaW4gUiBvciBSU3R1ZGlvLCB5b3Ugb25seSBuZWVkIHRvIGludm9rZSB0aGUgYGFibGluZWAgY29tbWFuZCAoZnJvbSB0aGUgY29uc29sZSkgdGhhdCB3ZSd2ZSB1c2VkIGFscmVhZHkgYW5kIHRoYXQncyBzaG93biBiZWxvdy4gSGVyZSwgaG93ZXZlciwgYmVjYXVzZSBJIHdhbnQgdG8gcHJvZHVjZSBhIHNlcGFyYXRlIHBsb3QgZnJvbSB0aGUgb25lIGFib3ZlLCBJIGhhdmUgdG8gcmUtcGxvdCB0aGUgZGF0YSB1c2luZyB0aGUgYWJvdmUgY29tbWFuZHMgYW5kIHRoZW4gaW52b2tlIGBhYmxpbmVgLioKICAKYGBge3IgZmlnLmhlaWdodD03fQpwYXIocHR5ID0gInMiKQpwbG90KENTcGQgfiBSU3BkLCBkYXRhID0gd20xLCAKICAgICB4bGFiID0gIldpbmQgc3BlZWQgYXQgcmVmZXJlbmNlIHNpdGUgKG0vcykiLCAKICAgICB5bGFiID0gIldpbmQgc3BlZWQgYXQgY2FuZGlkYXRlIHNpdGUgKG0vcykiLAogICAgIG1haW4gPSAiV2luZCBzcGVlZHMgYXQgcmVmZXJlbmNlIGFuZCBjYW5kaWRhdGUgc2l0ZXMiLAogICAgIHhsaW0gPSByYW5nZShjKENTcGQsIFJTcGQpKSwgeWxpbSA9IGMocmFuZ2UoYyhDU3BkLCBSU3BkKSkpKSAKIyBhYmxpbmUoKSB0YWtlcyB0d28gYXJndW1lbnRzOiBhIHNsb3BlIGFuZCBhbiBpbnRlcmNlcHQuIFdlIGNhbgojIGV4dHJhY3QgdGhlc2UgZnJvbSB0aGUgb2JqZWN0IFdpbmQubG0gKHdoaWNoIGlzIGEgbGlzdCkgYnkgCiMgdXNpbmcgdGhlICQgb3BlcmF0b3IsIGUuZy4sIFdpbmQubG0kY29lZmZpY2llbnRzICh0cnkgaXQhKSBhbmQKIyB1c2luZyB0aGF0IGFzIGFuIGFyZ3VtZW50IHRvIGFibGluZSgpOgphYmxpbmUoV2luZC5sbSRjb2VmKSAjIG9yIHNpbXBseSBhYmxpbmUoV2luZC5sbSkKYGBgICAKCgpiLiBDb25zdHJ1Y3QgdGhlIGZvdXIgZGlhZ25vc3RpYyBwbG90cyB0aGF0IHdlIGRpc2N1c3NlZCBpbiB0aGUgbGVjdHVyZS4gRG8geW91IHRoaW5rIHRoZSBzaW1wbGUgbGluZWFyIG1vZGVsIGlzIGEgZ29vZCBmaXQ/IFdoYXQgaW1wcm92ZW1lbnRzIG1pZ2h0IHlvdSBzdWdnZXN0PwoKYGBge3J9CnBhcihtZnJvdz1jKDIsMikpICAjIFBsYWNlcyA0IGdyYXBocyB0b2dldGhlciBvbiB0aGUgc2FtZSBwbG90dGluZyByZWdpb24KcGxvdChXaW5kLmxtKQpgYGAKClRoZSBpbnRlcnByZXRhdGlvbjoKCiAgICAgICAgIC0gUGxvdCAxIC0gUmVzaWR1YWxzIHZzIEZpdHRlZDogVGhlcmUgaXMgbm8gY2xlYXIgcGF0dGVybiwgZXZlbnRob3VnaCBsYXJnZSBmaXR0ZWQgdmFsdWVzIHNlZW0gdG8gaGF2ZSBzbWFsbGVyIHJlc2lkdWFscy4KCiAgICAgICAgIC0gUGxvdCAyIC0gU2NhbGUgLSBMb2NhdGlvbjogVGhlcmUgaXMgbm8gY2xlYXIgcGF0dGVybiwgZXZlbnRob3VnaCBsYXJnZSBmaXR0ZWQgdmFsdWVzIHNlZW0gdG8gaGF2ZSBzbWFsbGVyIHJlc2lkdWFscy4KCiAgICAgICAgIC0gUGxvdCAzIC0gUVEgcGxvdCBvZiBzdGFuZGFyZGlzZWQgcmVzaWR1YWxzOiB3aGlsZSBtb3N0IG9mIHRoZSBwb2ludHMgYXJlIG9uIHRoZSBzdHJhaWdodCBsaW5lLCBzb21lIHBvaW50cyBvbiB0aGUgdXBwZXIgcGFydCBhcmUgb2ZmIHRoZSBsaW5lcy4gTm9ybWFsaXR5IG1pZ2h0IG5vdCBiZSBzYXRpc2ZpZWQuCgogICAgICAgICAtIFBsb3QgNCAtIFJlc2lkdWFscyB2cyBMZXZlcmFnZTogQXMgJG49MTExNiQgdGhlbiB0aGUgY3V0LW9mZiBmb3IgQ29vaydzIGRpc3RhbmNlIGlzICREX2kgPiA0LyhuLTIpPTAuMDAzNi4kIFdlIGNhbiBzZWUgdGhhdCBtYW55IG9mIHRoZSBzdGFuZGFyZGlzZWQgcmVzaWR1YWxzIHdpdGggdGhlIGxldmVyYWdlIGdyZWF0ZXIgdGhhbiAwLjA0LiAKICAgICAgICAgCgojIyBRdWVzdGlvbiA0OiBIb3VzZSBzZWxsaW5nIHByaWNlIGRhdGEKCkEgc2V0IG9mIGRhdGEgb24gdGhlIHNlbGxpbmcgcHJpY2UgJFkkIChpbiBcJDEwLDAwMCkgYW5kIGFubnVhbCB0YXhlcyAkWCQgKGluIFwkMSwwMDApIGZvciAyNApob3VzZXMgaXMgYXZhaWxhYmxlIGF2YWlsYWJsZSBvbmxpbmUsIHtob3VzZXNlbGxpbmdwcmljZS50eHR9LgoKCmEuIEFzc3VtaW5nIHRoYXQgYSBzaW1wbGUgbGluZWFyIHJlZ3Jlc3Npb24gbW9kZWwgaXMgYXBwcm9wcmlhdGUsCm9idGFpbiB0aGUgbGVhc3Qgc3F1YXJlcyBmaXQgcmVsYXRpbmcgc2VsbGluZyBwcmljZSB0byB0YXhlcyBwYWlkLgpXaGF0IGlzIHRoZSBlc3RpbWF0ZSBvZiAkXHNpZ21hXjIkPwoKClJlYWQgZGF0YSBpbgoKYGBge3Igc2l6ZT0ic2NyaXB0c2l6ZSJ9CmhvdXNlID0gcmVhZC50YWJsZSgiaG91c2VzZWxsaW5ncHJpY2UudHh0IixoZWFkZXI9VCkKc3VtbWFyeShob3VzZSkKYGBgCgpTaW1wbGUgTGluZWFyIHJlZ3Jlc3Npb24gZml0CgpgYGB7ciBzaXplPSJzY3JpcHRzaXplIn0KaG91c2UubG08LWxtKHNhbGVzfnRheGVzLGRhdGE9aG91c2UpCnN1bW1hcnkoaG91c2UubG0pCmBgYAoKJFx3aWRlaGF0XGJldGFfMD0xMy4zMjAyJCwgJFx3aWRlaGF0XGJldGFfMT0zLjMyNDQkCgpgYGB7ciBzaXplPSJzY3JpcHRzaXplIn0KYW5vdmEoaG91c2UubG0pCmBgYAoKJFx3aWRlaGF0XHNpZ21hXjI9e1Jlc2lkdWFsIE1TfT04Ljc3JAoKCmIuIEZpbmQgdGhlIG1lYW4gc2VsbGluZyBwcmljZSBnaXZlbiB0aGF0IHRoZSB0YXhlcyBwYWlkIGFyZSAkNy41MCQuCgoKYGBge3Igc2l6ZT0ic2NyaXB0c2l6ZSJ9CnByZWRpY3QoaG91c2UubG0sbmV3ZGF0YT1kYXRhLmZyYW1lKHRheGVzPTcuNSksaW50ZXJ2YWw9ImNvbmZpZGVuY2UiLGxldmVsPTAuOTUpCmBgYAoKdGhlIG1lYW4gc2VsbGluZyBwcmljZSAkPTM4LjI1Mjk2JCB0aGF0IHRoZSB0YXhlcyBwYWlkIGFyZSAkWF8wPTcuNTAkLgoKCmMuIENvbnN0cnVjdCBhIGdyYXBoIG9mICRZJCB2ZXJzdXMgJFgkLiBUaGVuIGFkZCB0aGUgZml0dGVkIGxpbmUsCnRoZSA5NVwlIGNvbmZpZGVuY2UgaW50ZXJ2YWwgb2YgdGhlIG1lYW4gcmVzcG9uc2UsIGFuZCB0aGUgOTVcJQpwcmVkaWN0aW9uIGludGVydmFsIG9mIHRoZSBuZXcgYWN0dWFsIHZhbHVlcyBvbiB0aGUgZ3JhcGguCgoKYGBge3Igc2l6ZT0ic2NyaXB0c2l6ZSJ9CndpdGgoaG91c2UscGxvdChzYWxlc350YXhlcyx0eXBlPSJwIikpCndpdGgoaG91c2UsbGluZXMoZml0dGVkKGhvdXNlLmxtKX50YXhlcykpCm5ldyA9IGRhdGEuZnJhbWUodGF4ZXM9c2VxKDMsMTAsLjEpKQpDSXMgPSBwcmVkaWN0KGhvdXNlLmxtLG5ldyxpbnRlcnZhbD0iY29uZmlkZW5jZSIpClBJcyA9IHByZWRpY3QoaG91c2UubG0sbmV3LGludGVydmFsPSJwcmVkaWN0IikKbWF0cG9pbnRzKG5ldyR0YXhlcyxDSXMsbHR5PWMoMSwyLDIpLGNvbD1jKCJibGFjayIsInJlZCIsInJlZCIpLHR5cGU9ImwiKQptYXRwb2ludHMobmV3JHRheGVzLFBJcyxsdHk9YygxLDIsMiksY29sPWMoImJsYWNrIiwiYmx1ZSIsImJsdWUiKSx0eXBlPSJsIikKYGBgCgoKZC4gUGVyZm9ybSBkaWFnbm9zdGljIGNoZWNraW5nIGZvciB0aGUgZml0dGVkIG1vZGVsIGluIChhKSB1c2luZyDigJxwbG90KGZpbGUubG0pLuKAnSBJbnRlcnByZXQgdGhlIG91dHB1dHMuCgpgYGB7cn0KcGFyKG1mcm93PWMoMiwyKSkKcGxvdChob3VzZS5sbSkKYGBgCgoKKyBUaGUgdG9wIGxlZnQgcGxvdCBzaG93cyB0aGUgcmVzaWR1YWxzIGFnYWluc3QgZml0dGVkIHZhbHVlcyB0byBjaGVjayByYW5kb21uZXNzIChubyBwYXR0ZXJuKSBhbmQgbGluZWFyaXR5LiAKVGhlIHNtb290aGluZyBjdXJ2ZSBzaG93cyBhIHJlYXNvbmFibGUgbGluZWFyIHJlbGF0aW9uc2hpcCBhbmQgbm8gcGF0dGVybi4KCisgVGhlIGJvdHRvbSBsZWZ0IHByb3ZpZGVzIHRoZSBzdGFuZGFyZGlzZWQgcmVzaWR1YWxzIGFnYWluc3QgZml0dGVkIHZhbHVlcyB0byBjaGVjayByYW5kb21uZXNzIChubyBwYXR0ZXJuKSBhbmQgY29uc3RhbnQgdmFyaWFuY2UuIFRoZSBzbW9vdGhpbmcgY3VydmUgdXNpbmcgc3RhbmRhcmRpc2VkIHJlc2lkdWFscyBpcyBhIGN1cnZlIHdoaWNoIG1lYW5zIHRoYXQgaW5kZXBlbmRlbmNlIGFuZCBjb25zdGFudCB2YXJpYW5jZSBtYXkgbm90IGJlIHNhdGlzZmllZC4KCisgVGhlIHRvcCByaWdodCBwbG90IGlzIGEgbm9ybWFsIFHigJNRIHBsb3QuIE1vc3Qgb2YgdGhlIG9ic2VydmF0aW9ucyBsaWUgYXJvdW5kIHRoZSBzdHJhaWdodCBsaW5lIGV4Y2VwdCB0aGUgdHdvIHBvaW50cywgY29uZmlybWluZyBOb3JtYWxpdHkuCgorIFRoZSBib3R0b20gcmlnaHQgcGxvdCBvZiBzdGFuZGFyZGl6ZWQgcmVzaWR1YWxzIGFnYWluc3QgbGV2ZXJhZ2UgZW5hYmxlcyBvbmUKdG8gcmVhZGlseSBpZGVudGlmeSBhbnkg4oCYYmFk4oCZIGxldmVyYWdlIHBvaW50cy4gCgpgYGB7cn0KIyBjaGVjayBoZWxwIGZ1bmN0aW9uIGZpcnN0CmhvdXNlLmxldjwtaGF0dmFsdWVzKGhvdXNlLmxtKQpob3VzZS5sZXYKYGBgCmBgYHtyfQpzdGQucmVzLmg9cnN0YW5kYXJkKGhvdXNlLmxtKQojc3RkLnJlcy5oCnNvcnQoc3RkLnJlcy5oKQpgYGAKCiAgICAgICAgLSBSZWNhbGwgdGhhdCB0aGUgcnVsZSBmb3Igc2ltcGxlIGxpbmVhciByZWdyZXNzaW9uIGZvciBjbGFzc2lmeWluZyBhIHBvaW50IGFzIGEgbGV2ZXJhZ2UKICAgICAgICBwb2ludCBpcyBpZiBsZXZlcmFnZSAkaF97aWl9ID4gNC8gbi4kIEFzICRuPTI0JCwgdGhlIHJ1bGUgaXMgJGhfe2lpfSA+IDAuMTY3LiQgQXMgbGV2ZXJhZ2UgJGhfe2lpfSQgaW4gdGhlICAKICAgICAgICBhYm92ZSBvdXRwdXQgc2hvd3MgdGhhdCBvbmUgcG9pbnQgKG9ic2VydmF0aW9uIG5vIDI0KSB3aXRoICRoX3tpaX09MC4xNzE3NyA+IDAuMTY3JCAsIHRoZW4gdGhlcmUgaXMgb25lCiAgICAgICAgbGV2ZXJhZ2UgcG9pbnQuCgogICAgICAgIC0gUmVjYWxsIHRoYXQgd2UgY2xhc3NpZnkgcG9pbnRzIGFzIG91dGxpZXJzIGlmIHRoZWlyIHN0YW5kYXJkaXplZCByZXNpZHVhbHMgaGF2ZQogICAgICAgIGFic29sdXRlIHZhbHVlIGdyZWF0ZXIgdGhhbiAyLiBUaGVyZSBpcyBvbmUgb2JzZXJ2YXRpb24gKG5vIDE1KSB3aXRoIHRoZSBzdGFuZGFyZCByZXNpZHVhbCBpcyBncmVhdGVyIHRoYW4gIAogICAgICAgIDIuIEhvd2V2ZXIgb2JzZXJ2YXRpb24gbnVtYmVyIDI0LCB0aGUgbGV2ZXJhZ2UgcG9pbnQsICB3aXRoIHN0YW5kYXJkIHJlc2lkdWFsIGxlc3MgdGhhbiAyIGlzIGEgZ29vZAogICAgICAgIGxldmVyYWdlIHBvaW50LgogICAgICAgIAogICAgICAgIAojIyBRdWVzdGlvbiA1IEJpZCBkYXRhIChTaGVhdGhlciwgMjAwOSkKCkEgYnVpbGRpbmcgbWFpbnRlbmFuY2UgY29tcGFueSBpcyBwbGFubmluZyB0byBzdWJtaXQgYSBiaWQgb24gYSBjb250cmFjdCB0byBjbGVhbiBjb3Jwb3JhdGUKb2ZmaWNlcyBzY2F0dGVyZWQgdGhyb3VnaG91dCBhbiBvZmZpY2UgY29tcGxleC4gVGhlIGNvc3RzIGluY3VycmVkIGJ5IHRoZSBtYWludGVuYW5jZSBjb21wYW55IGFyZQpwcm9wb3J0aW9uYWwgdG8gdGhlIG51bWJlciBvZiBjbGVhbmluZyBjcmV3cyBuZWVkZWQgZm9yIHRoaXMgdGFzay4gUmVjZW50IGRhdGEgYXJlIGF2YWlsYWJsZSBmb3IgdGhlIG51bWJlcgpvZiByb29tcyB0aGF0IHdlcmUgY2xlYW5lZCBieSB2YXJ5aW5nIG51bWJlcnMgb2YgY3Jld3MuIEZvciBhIHNhbXBsZSBvZiA1MyBkYXlzLCByZWNvcmRzIHdlcmUga2VwdCBvZiB0aGUgCm51bWJlciBvZiBjcmV3cyB1c2VkIGFuZCB0aGUgbnVtYmVyIG9mIHJvb21zIHRoYXQgd2VyZSBjbGVhbmVkIGJ5IHRob3NlIGNyZXdzLgpUaGUgZGF0YSBjYW4gYmUgZm91bmQgaW4gdGhlIGZpbGUgKmNsZWFuaW5nLnR4dCouCgpUaGUgYWltIGlzIHRvIGRldmVsb3AgYSByZWdyZXNzaW9uIGVxdWF0aW9uIHRvIG1vZGVsIHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiB0aGUgCm51bWJlciBvZiByb29tcyBjbGVhbmVkIGFuZCB0aGUgbnVtYmVyIG9mIGNyZXdzLgoKQ29tcGxldGUgdGhlIGZvbGxvd2luZyB0YXNrcy4KCihhKS4gRml0IHRoZSBsZWFzdCBzcXVhcmVzIGxpbmUgdG8gdGhlIGRhdGEgdXNpbmcgUi4gRXhwbGFpbiB0aGUgZml0dGVkIG1vZGVsLCBieSBpbnRlcnByZXRpbmcgdGhlIHNsb3BlIGFuZCBpbnRlcmNlcHQuCgpgYGB7cn0KYmlkPXJlYWQudGFibGUoImNsZWFuaW5nLnR4dCIsIGhlYWRlcj1UKQpoZWFkKGJpZCkKYGBgCgpgYGB7cn0KYmlkLmxtPWxtKFJvb21zIH4gQ3Jld3MsIGRhdGE9YmlkKSAjIyB0aGUgTFMgbGluZQpwbG90KFJvb21zIH4gQ3Jld3MsIGRhdGE9YmlkLCB4bGFiPSJOdW1iZXIgb2YgQ3Jld3MiLCB5bGFiPSJOdW1iZXIgb2YgUm9vbXMiKQphYmxpbmUoYmlkLmxtKQpzdW1tYXJ5KGJpZC5sbSkKYGBgCgpUaGUgZXF1YXRpb24gb2YgdGhlIGxlYXN0IHNxdWFyZXMgbGluZSBvZiBiZXN0IGZpdCBpcwoKJCRSb29tcyA9IDEuNzggKyAzLjcwIENyZXdzLiQkCgoKVGhlIGludGVyY2VwdCBpcyAkMS43OCBcYXBwcm94IDIkIHdoaWNoIGlzIHdoZXJlIHRoZSBsaW5lIG9mIGJlc3QgZml0IGNyb3NzZXMgdGhlIFJvb21zIGF4aXMuIFRoZQppbnRlcmNlcHQgaW4gdGhlIG1vZGVsIGhhcyB0aGUgZm9sbG93aW5nIGludGVycHJldGF0aW9uOiBmb3IgQ3Jld3M9MCwgdGhlCmF2ZXJhZ2Ugb2YgbnVtYmVyIG9mIGNsZWFuZWQgcm9vbSBpcyAyLgoKVGhlIHNsb3BlIG9mIHRoZSBsaW5lIGlzICQzLjcwIFxhcHByb3ggNCQuIFRodXMsIHdlIHNheSB0aGF0IGZvciBlYWNoCmFkZGl0aW9uYWwgY3JldywgaXQgaXMgcHJlZGljdGVkIHRvIGFkZCA0IHJvb21zIGFyZSBiZWluZyBjbGVhbmVkLiAKCihiKS4gQ29uc3RydWN0IHJlc2lkdWFsIGRpYWdub3N0aWMgcGxvdHMsIGFuZCBhc3Nlc3Mgd2hldGhlciB5b3UgdGhpbmsgdGhhdCB0aGUgYXNzdW1wdGlvbnMgZm9yIGxpbmVhciByZWdyZXNzaW9uIGhhdmUgYmVlbiBzYXRpc2ZpZWQuIFlvdSBjYW4gdXNlIHRoZSBmdW5jdGlvbiBgcnN0dWRlbnRgIChvciBgcnN0YW5kYXJkYCkgdG8gZmlyc3Qgc3RhbmRhcmRpemUgdGhlIHJlc2lkdWFscy4KCkZpcnN0LCB3ZSBtYW51YWxseSBjaGVjayB0aGUgKm5vcm1hbGl0eSB0aHJvdWdoIGhpc3RvZ3JhbXMgYW5kIFFRLXBsb3RzIG9mIHJlc2lkdWFscyBhbmQgc3RhbmRhcmRpc2VkIHJlc2lkdWFscy4qCgpgYGB7cn0KcmVzLmJpZD1iaWQubG0kcmVzaWR1YWxzCnN0ZC5yZXMuYmlkPXJzdGFuZGFyZChiaWQubG0pICAjIyBzdGFuZGFyZGlzZWQgcmVzaWR1YWxzCnBhcihtZnJvdz1jKDIsMikpICAjIyBwbG90dGluZyA0IHBsb3RzIHRvIGNoZWNrIG5vcm1hbGl0eQpoaXN0KHJlcy5iaWQpCmhpc3Qoc3RkLnJlcy5iaWQpCnFxbm9ybShyZXMuYmlkKQpxcWxpbmUocmVzLmJpZCkKcXFub3JtKHN0ZC5yZXMuYmlkKQpxcWxpbmUoc3RkLnJlcy5iaWQpCnBhcihtZnJvdz1jKDEsMSkpCmBgYAoKRnJvbSB0aGUgYWJvdmUgaGlzdG9ncmFtcyBhbmQgUVEtcGxvdHMsIHRoZSBub3JtYWxpdHkgaXMgc2F0aXNmaWVkLgoKYGBge3J9CnBhcihtZnJvdz1jKDIsMikpCnBsb3QocmVzLmJpZCwgeGxhYj0iVGltZSIsIHlsYWI9IlJlc2lkdWFscyIpICMjIFJlc2lkdWFscyB2cyBUaW1lCnBsb3Qoc3RkLnJlcy5iaWQseGxhYj0iVGltZSIsIHlsYWI9IlN0YW5kYXJkaXNlZCBSZXNpZHVhbHMiKQpwbG90KGJpZCRDcmV3cyxyZXMuYmlkLCB4bGFiPSJOdW1iZXIgb2YgQ3Jld3MiLCB5bGFiPSJSZXNpZHVhbHMiKSAjIFJlc2lkdWFscyB2cyB4CnBsb3QoYmlkJENyZXdzLHN0ZC5yZXMuYmlkLCAgeGxhYj0iTnVtYmVyIG9mIENyZXdzIiwgeWxhYj0iU3RhbmRhcmRpc2VkIFJlc2lkdWFscyIpCmBgYAoKICAgICAtIFRoZSBuZXh0IHJlc2lkdWFsIGFuYWx5c2lzIGlzIHRvIGNoZWNrIGFib3V0IHJhbmRvbW5lc3MgKGluZGVwZW5kZW5jZSkgYW5kIGNvbnN0YW50IHZhcmlhbmNlLiBXZSBwbG90IGJvdGgKICAgICByZXNpZHVhbHMgYW5kIHN0YW5kYXJkaXNlZCByZXNpZHVhbHMgYWdhaW5zdCB0aW1lICh0b3AgbGVmdCBhbmQgdG9wIHJpZ2h0KS4gRnJvbSB0aGVzZSBwbG90cyB3ZSBjYW4gY29uZmlybSB0aGUKICAgICB0aGUgcmVzaWR1YWwgYXJlIHJhbmRvbSBzY2F0dGVyZWQgd2l0aCBubyBwYXR0ZXJuIHdoYXRzb2V2ZXIuIEhvd2V2ZXIsIHRoZXJlIHNlZW1zIHRvIHNob3cgYW4gaW5jcmVhc2luZyB0cmVuZCBmb3IgdmFyaWFuY2VzLgoKICAgICAtIFRoZSBib3R0b20gbGVmdCBwbG90IHNob3dzIHRoZSByZXNpZHVhbHMgYWdhaW5zdCBOdW1iZXIgb2YgQ3Jld3MgdG8gY2hlY2sgcmFuZG9tbmVzcyAobm8gcGF0dGVybikgYW5kIGNvbnN0YW50IHZhcmlhbmNlLiBUaGUgYm90dG9tIHJpZ2h0IHBsb3QgcHJvdmlkZXMgdGhlIHN0YW5kYXJkaXNlZCByZXNpZHVhbHMgYWdhaW5zdCBmaXR0ZWQgdmFsdWVzIHRvIGNoZWNrIHJhbmRvbW5lc3MgKG5vIHBhdHRlcm4pIGFuZCBjb25zdGFudCB2YXJpYW5jZS4gCiAgCiAgICAtIEl0IGlzIGNsZWFyIHRoYXQgIHRoZSB2YXJpYWJpbGl0eSBpbiB0aGUgc3RhbmRhcmRpemVkIHJlc2lkdWFscyB0ZW5kcyB0byBpbmNyZWFzZSAgd2l0aCB0aGUgbnVtYmVyIG9mIGNyZXdzLiBUaHVzLCB0aGUgYXNzdW1wdGlvbiB0aGF0IHRoZSB2YXJpYW5jZSBvZiB0aGUgZXJyb3JzIGlzIGNvbnN0YW50IGFwcGVhcnMgdG8gYmUgdmlvbGF0ZWQgaW4gdGhpcyBjYXNlLiAKCihjKS4gUGVyZm9ybSBkaWFnbm9zdGljIGNoZWNraW5nIGZvciB0aGUgZml0dGVkIG1vZGVsIGluIChhKSB1c2luZyAicGxvdChmaWxlLmxtKS4iIEludGVycHJldCB0aGUgb3V0cHV0cy4KCmBgYHtyfQpwYXIobWZyb3c9YygyLDIpKQpwbG90KGJpZC5sbSkKYGBgCgogICAgICAgLSAgVGhlIHRvcCBsZWZ0IHBsb3Qgc2hvd3MgdGhlIHJlc2lkdWFscyBhZ2FpbnN0IGZpdHRlZCB2YWx1ZXMgdG8gY2hlY2sgcmFuZG9tbmVzcyAobm8gcGF0dGVybikgYW5kIGxpbmVhcml0eS4gIFRoZSBzbW9vdGhpbmcgY3VydmUgc2hvd3MgYSByZWFzb25hYmxlIGxpbmVhciByZWxhdGlvbnNoaXAgYW5kIG5vIHBhdHRlcm4uCgogICAgICAgLSBUaGUgYm90dG9tIGxlZnQgcHJvdmlkZXMgdGhlIHNxdWFyZWQgcm9vdCBvZiBzdGFuZGFyZGlzZWQgcmVzaWR1YWxzIGFnYWluc3QgZml0dGVkIHZhbHVlcyB0byBjaGVjayByYW5kb21uZXNzIChubyBwYXR0ZXJuKSBhbmQgY29uc3RhbnQgdmFyaWFuY2UuIFRoZSBzbW9vdGhpbmcgY3VydmUgdXNpbmcgc3RhbmRhcmRpc2VkIHJlc2lkdWFscyBpcyBhbiBpbmNyZWFzaW5nIHRyZW5kIHdoaWNoIG1lYW5zIHRoYXQgY29uc3RhbnQgdmFyaWFuY2UgbWF5IG5vdCBiZSBzYXRpc2ZpZWQuCgogICAgICAgIC0gVGhlIHRvcCByaWdodCBwbG90IGlzIGEgbm9ybWFsIFHigJNRIHBsb3QuIE1vc3Qgb2YgdGhlIG9ic2VydmF0aW9ucyBsaWUgYXJvdW5kIHRoZSBzdHJhaWdodCBsaW5lIGV4Y2VwdCB0aGUgdHdvIHBvaW50cywgY29uZmlybWluZyBOb3JtYWxpdHkuCgogICAgICAgIC0gIFRoZSBib3R0b20gcmlnaHQgcGxvdCBvZiBzdGFuZGFyZGl6ZWQgcmVzaWR1YWxzIGFnYWluc3QgbGV2ZXJhZ2UgZW5hYmxlcyBvbmUgdG8gcmVhZGlseSBpZGVudGlmeSBhbnkg4oCYYmFk4oCZIGxldmVyYWdlIHBvaW50cyAoaWUgbGFyZ2UgbGV2ZXJhZ2UgYW5kIGxhcmdlIHN0YW5kYXJkaXNlZCByZXNpZHVhbHMpIAoKKGQpLiBBcyB0aGUgIGRhdGEgIG9uIGVhY2ggYXhpcyBhcmUgIGluIHRoZSBmb3JtIG9mIGNvdW50cyBhbmQgYXJlIG1lYXN1cmVkIGluIHRoZSBzYW1lIHVuaXRzLCB0aGUgc3F1YXJlIApyb290IHRyYW5zZm9ybWF0aW9uIG9mIGJvdGggdGhlIHByZWRpY3RvciB2YXJpYWJsZSBhbmQgdGhlIHJlc3BvbnNlIHZhcmlhYmxlIHNob3VsZCBiZSBpbXBsZW1lbnRlZC4gQXBwbHkgCnRoZXNlIHRyYW5zZm9ybWF0aW9ucyBhbmQgcmVwZWF0IChhKS4KCgpgYGB7cn0KYmlkLnNxLmxtPWxtKHNxcnQoUm9vbXMpIH4gc3FydChDcmV3cyksIGRhdGE9YmlkKSAjIyB0aGUgTFMgbGluZQpwbG90KHNxcnQoUm9vbXMpIH4gc3FydChDcmV3cyksIGRhdGE9YmlkLCB4bGFiPSJTcXVhcmUgUm9vdCBvZiBOdW1iZXIgb2YgQ3Jld3MiLCB5bGFiPSJTcXVhcmUgUm9vdCBvZiBOdW1iZXIgb2YgUm9vbXMiKQphYmxpbmUoYmlkLnNxLmxtKQpzdW1tYXJ5KGJpZC5zcS5sbSkKYGBgCgooZSkuIFBlcmZvcm0gZGlhZ25vc3RpYyBjaGVja2luZyBmb3IgdGhlIGZpdHRlZCBtb2RlbCBpbiAoZCkgdXNpbmcgInBsb3QoZmlsZS5sbSkuIiBJbnRlcnByZXQgdGhlIG91dHB1dHMuCgoKYGBge3J9CnBhcihtZnJvdz1jKDIsMikpCnBsb3QoYmlkLnNxLmxtKQpgYGAKCgogICAgICAgICAtIEFmdGVyIHRoZSB0cmFuc2Zvcm1hdGlvbiwgdGhlIGJvdHRvbSBsZWZ0LWhhbmQgcGxvdCBmdXJ0aGVyIGRlbW9uc3RyYXRlcyB0aGUgCiAgICAgICAgIGJlbmVmaXQgb2YgdGhlIHNxdWFyZSByb290IHRyYW5zZm9ybWF0aW9uIGluIHRlcm1zIG9mIHN0YWJpbGl6aW5nIHRoZSBlcnJvciB0ZXJtLiAgCiAgICAgICAgIAogICAgICAgICAtIFRodXMsIHRha2luZyB0aGUgc3F1YXJlIHJvb3Qgb2YgYm90aCB0aGUgIHggIGFuZCB0aGUgIHkgIHZhcmlhYmxlcyBoYXMgc3RhYmlsaXplZAogICAgICAgICB0aGUgdmFyaWFuY2Ugb2YgdGhlIHJhbmRvbSBlcnJvcnMgYW5kIGhlbmNlIHByb2R1Y2VkIGEgdmFsaWQgbW9kZWwuICAKCgooZikuIFByZWRpY3QgdGhlIG51bWJlciBvZiByb29tcyB0aGF0IGNhbiBiZSBjbGVhbmVkIGJ5IDQgY3Jld3MgYW5kIGJ5IDE2IGNyZXdzIGFuZCBpdHMgOTUlIGNvbmZpZGVuY2UgaW50ZXJ2YWxzIHVzaW5nIHRoZSBtb2RlbHMgaW4gKGEpIGFuZCAoZCkgcmVzcGVjdGl2ZWx5LgoKVXNpbmcgKGEpCgpgYGB7cn0KY29uZi5wcmVkMD1wcmVkaWN0KGJpZC5sbSxuZXdkYXRhPWRhdGEuZnJhbWUoQ3Jld3M9Yyg0LDE2KSksaW50ZXJ2YWw9InByZWRpY3Rpb24iLGxldmVsPTAuOTUpCmNvbmYucHJlZDAKYGBgCgpVc2luZyAoZCkKCmBgYHtyfQpjb25mLnByZWQwLnNxPXByZWRpY3QoYmlkLnNxLmxtLG5ld2RhdGE9ZGF0YS5mcmFtZShDcmV3cz1jKDQsMTYpKSxpbnRlcnZhbD0icHJlZGljdGlvbiIsbGV2ZWw9MC45NSkKY29uZi5wcmVkMC5zcV4yICAjIyBhcyB0aGlzIHdhcyBzcXVhcmUgcm9vdApgYGAKCiAgICAgICAtIFdlIGNhbiBzZWUgdGhhdCB0aGUgcHJlZGljdGlvbiBpbnRlcnZhbCBiYXNlZCBvbiB0aGUgdHJhbnNmb3JtZWQgZGF0YSBpcyBuYXJyb3dlciAKICAgICAgIHRoYW4gdGhhdCAgYmFzZWQgb24gdGhlIHVudHJhbnNmb3JtZWQgZGF0YSB3aGVuIHRoZSBudW1iZXIgb2YgY3Jld3MgaXMgNCAoNy43OCwgCiAgICAgICAyNy4yMSkgdnMgKDEuNTgsIDMxLjU5KSBhbmQgd2lkZXIgd2hlbiB0aGUgbnVtYmVyIG9mIGNyZXdzIGlzIDE2IFsoNDMuMzMsIDgxLjU1KSBpcyAKICAgICAgIHdpZGVyIHRoYW4gKDQ1LjgxLCA3Ni4xOSldLiAKCiAgICAgICAtIFRoaXMgaXMgZXhwZWN0ZWQgYXMgdGhlIG9yaWdpbmFsIHNjYWxlIHRoZSBkYXRhIGhhdmUgdmFyaWFuY2Ugd2hpY2ggaW5jcmVhc2VzIGFzIAogICAgICAgdGhlICB4IC12YXJpYWJsZSBpbmNyZWFzZXMgd2hpY2ggbWVhbnMgdGhhdCByZWFsaXN0aWMgcHJlZGljdGlvbiBpbnRlcnZhbHMgd2lsbAogICAgICAgZ2V0IHdpZGVyIGFzIHRoZSAgeCAtdmFyaWFibGUgaW5jcmVhc2VzLiAgCgogICAgICAtIEluIHN1bW1hcnksIGlnbm9yaW5nIG5vbmNvbnN0YW50IHZhcmlhbmNlIGluIHRoZSByYXcgZGF0YSBmcm9tIHRoaXMgZXhhbXBsZSBsZWQgdG8gCiAgICAgIGludmFsaWQgcHJlZGljdGlvbiBpbnRlcnZhbHMuIAogICAgICAKICAgICAg